[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\n    end_of_line = lf\n    trim_trailing_whitespace = true\n    insert_final_newline = true\n    indent_style = space\n    indent_size = 4\n    charset = utf8\n\n[{package.json, package-lock.json}]\n    indent_size = 2\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n    \"extends\": \"airbnb\",\n    \"rules\": {\n        \"indent\": [2, 4],\n        \"no-underscore-dangle\": [2, { \"allowAfterThis\": true }],\n        \"no-restricted-syntax\": [\"error\", \"ForInStatement\", \"LabeledStatement\", \"WithStatement\"],\n        \"newline-per-chained-call\": \"off\",\n        \"max-len\": [2, 255, 4],\n        \"no-param-reassign\": 0,\n        \"spaced-comment\": [2, \"always\", { \"markers\": [\"/\", \"!\"] }],\n        \"no-plusplus\": 0,\n        \"operator-linebreak\":\"off\"\n    },\n    \"env\": {\n        \"amd\": true,\n        \"node\": true,\n        \"commonjs\": true,\n        \"es6\": true,\n        \"browser\": true\n    },\n    \"globals\": {\n        \"VerEx\": true\n    }\n}\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: npm\n    directory: \"/\"\n    schedule:\n      interval: daily\n    open-pull-requests-limit: 1000000\n  - package-ecosystem: bundler\n    directory: \"/docs\"\n    schedule:\n      interval: daily\n    open-pull-requests-limit: 1000000\n"
  },
  {
    "path": ".github/workflows/automerge.yml",
    "content": "name: Dependabot auto-merge\non: pull_request\n\npermissions:\n  pull-requests: write\n  contents: write\n\njobs:\n  dependabot:\n    runs-on: ubuntu-latest\n    if: ${{ github.actor == 'dependabot[bot]' }}\n    steps:\n      - name: Enable auto-merge for Dependabot PRs\n        env:\n          PR_URL: ${{github.event.pull_request.html_url}}\n          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}\n        run: |\n          function get_pending_jobs() {\n            gh pr view \"$PR_URL\" --json statusCheckRollup --jq '.statusCheckRollup | map(select(.name != \"dependabot\")) | map(select(.status != \"COMPLETED\")).[]'\n          }\n\n          function get_failed_jobs() {\n            gh pr view \"$PR_URL\" --json statusCheckRollup --jq '.statusCheckRollup | map(select(.name != \"dependabot\")) | map(select(.conclusion != \"SUCCESS\")).[]'\n          }\n\n          function wait_until_completed() {\n            while [[ $(get_pending_jobs) ]]\n            do\n              sleep 5\n            done\n          }\n\n          function fail_if_unsuccessful() {\n            if [[ $(get_failed_jobs) ]]; then\n              echo \"Some jobs failed, unable to automerge\"\n              exit 1\n            fi\n          }\n\n          function auto_merge() {\n            gh pr merge --auto --rebase \"$PR_URL\"\n          }\n\n          wait_until_completed && \\\n          fail_if_unsuccessful && \\\n          auto_merge\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: '33 0 * * 1'\n\njobs:\n    analyze:\n        name: Analyze\n        runs-on: ubuntu-latest\n\n        strategy:\n            fail-fast: false\n            matrix:\n                language: ['javascript']\n                # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]\n                # Learn more:\n                # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed\n\n        steps:\n            - name: Checkout repository\n              uses: actions/checkout@v2\n\n            # Initializes the CodeQL tools for scanning.\n            - name: Initialize CodeQL\n              uses: github/codeql-action/init@v1\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                  # queries: ./path/to/local/query, your-org/your-repo/queries@main\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@v1\n\n            # ℹ️ Command-line programs to run using the OS shell.\n            # 📚 https://git.io/JvXDl\n\n            # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines\n            #    and modify them (or add more) to build your code if your project\n            #    uses a compiled language\n\n            #- run: |\n            #   make bootstrap\n            #   make release\n\n            - name: Perform CodeQL Analysis\n              uses: github/codeql-action/analyze@v1\n"
  },
  {
    "path": ".github/workflows/gh-pages.yml",
    "content": "name: Build docs/ folder\non: pull_request\njobs:\n    test:\n        name: Build docs/ folder\n        runs-on: ubuntu-latest\n        steps:\n            - uses: actions/checkout@v2\n            - uses: actions/setup-ruby@v1\n            - run: |\n                  cd docs\n                  gem install bundler --version '~> 1'\n                  bundle install\n                  bundle exec jekyll build\n            - run: |\n                  git add -A                      # Make sure new files are accounted\n                  git diff --exit-code --cached   # Expect no changes in git\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Run tests\non: pull_request\njobs:\n    test:\n        name: Run tests on Node.js ${{ matrix.node-version }}\n        runs-on: ubuntu-latest\n        strategy:\n            matrix:\n                node-version: [\"16\", \"15\", \"14\", \"13\", \"12\"]\n        steps:\n            - uses: actions/checkout@v2\n            - uses: actions/setup-node@v1\n              with:\n                  node-version: ${{ matrix.node-version }}\n            - run: npm ci\n            - run: npm run test:verbose\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.DS_Store\n.idea/\n.vscode/\n.nyc_output\ndocs/_site\ndocs/.sass-cache\ndocs/.jekyll-metadata\n"
  },
  {
    "path": ".mdlintrc.json",
    "content": "{\n    \"heading-increment\": true,\n    \"first-heading-h1\": { \"level\": 1 },\n    \"heading-style\": { \"style\": \"atx\" },\n    \"ul-style\": { \"style\": \"dash\" },\n    \"list-indent\": true,\n    \"ul-start-left\": true,\n    \"ul-indent\": { \"indent\": 4 },\n    \"no-trailing-spaces\": true,\n    \"no-hard-tabs\": true,\n    \"no-reversed-links\": true,\n    \"no-multiple-blanks\": { \"maximum\": 1 },\n    \"line-length\": false,\n    \"commands-show-output\": true,\n    \"no-missing-space-atx\": true,\n    \"no-multiple-space-atx\": true,\n    \"no-missing-space-closed-atx\": true,\n    \"no-multiple-space-closed-atx\": true,\n    \"blanks-around-headings\": true,\n    \"heading-start-left\": true,\n    \"no-duplicate-heading\": true,\n    \"single-h1\": false,\n    \"no-trailing-punctuation\": true,\n    \"ol-prefix\": { \"style\": \"ordered\" },\n    \"list-marker-space\": 1,\n    \"blanks-around-fences\": true,\n    \"blanks-around-lists\": true,\n    \"no-inline-html\": false,\n    \"no-bare-urls\": true,\n    \"hr-style\": { \"style\": \"___\" },\n    \"no-emphasis-as-heading\": true,\n    \"no-space-in-emphasis\": true,\n    \"no-space-in-code\": false,\n    \"no-space-in-links\": true,\n    \"fenced-code-language\": false,\n    \"first-line-h1\": true,\n    \"no-empty-links\": true,\n    \"no-alt-text\": true\n}\n"
  },
  {
    "path": "Gruntfile.js",
    "content": "module.exports = function gruntConfig(grunt) {\n    grunt.initConfig({\n        pkg: grunt.file.readJSON('package.json'),\n\n        eslint: {\n            target: ['VerbalExpressions.js', 'test/tests.js', 'Gruntfile.js'],\n        },\n\n        ava: {\n            test: ['test/tests.js'],\n            options: {\n                nyc: true,\n            },\n\n            verbose: {\n                test: ['test/tests.js'],\n                options: {\n                    verbose: true,\n                    nyc: true,\n                },\n            },\n        },\n\n        babel: {\n            options: {\n                sourceMap: true,\n                presets: [['@babel/preset-env', { modules: false }]],\n                plugins: [\n                    ['transform-builtin-extend', { globals: ['RegExp'] }],\n                ],\n            },\n            dist: {\n                files: {\n                    'dist/verbalexpressions.js': 'VerbalExpressions.js',\n                },\n            },\n        },\n\n        umd: {\n            all: {\n                options: {\n                    src: 'dist/verbalexpressions.js',\n                    objectToExport: 'VerEx',\n                    amdModuleId: 'VerEx',\n                    globalAlias: 'VerEx',\n                },\n            },\n        },\n\n        uglify: {\n            options: {\n                banner:\n                    '/*!\\n' +\n                    '* <%= pkg.name %> JavaScript Library v<%= pkg.version %>\\n' +\n                    '* <%= pkg.homepage %>\\n' +\n                    '*\\n' +\n                    '* Released under the <%= pkg.license %> license\\n' +\n                    '*/\\n',\n                sourceMap: true,\n            },\n            dist: {\n                files: {\n                    'dist/verbalexpressions.min.js': [\n                        'dist/verbalexpressions.js',\n                    ],\n                },\n            },\n        },\n\n        sourcemap_localize: {\n            options: {\n                localize_to: '..',\n            },\n            build: {\n                files: {\n                    src: ['dist/*.min.js.map'],\n                },\n            },\n        },\n\n        markdownlint: {\n            options: {\n                config: grunt.file.readJSON('.mdlintrc.json'),\n            },\n            src: ['README.md', 'docs/*.md', 'docs/VerbalExpression/*.md'],\n        },\n    });\n\n    grunt.loadNpmTasks('grunt-eslint');\n    grunt.loadNpmTasks('grunt-ava');\n    grunt.loadNpmTasks('grunt-babel');\n    grunt.loadNpmTasks('grunt-umd');\n    grunt.loadNpmTasks('grunt-contrib-uglify');\n    grunt.loadNpmTasks('grunt-sourcemap-localize');\n    grunt.loadNpmTasks('grunt-markdownlint');\n\n    grunt.registerTask('default', ['test']);\n    grunt.registerTask('test', [\n        'compile',\n        'eslint',\n        'markdownlint',\n        'ava:test',\n    ]);\n    grunt.registerTask('test:verbose', ['compile', 'eslint', 'ava:verbose']);\n    grunt.registerTask('compile', ['babel', 'umd:all']);\n    grunt.registerTask('build', [\n        'compile',\n        'ava:test',\n        'uglify',\n        'sourcemap_localize',\n    ]);\n};\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2017 jehna\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# VerbalExpressions\n\n[![Build Status](https://travis-ci.org/VerbalExpressions/JSVerbalExpressions.svg)](https://travis-ci.org/VerbalExpressions/JSVerbalExpressions)\n[![Latest Version](https://img.shields.io/npm/v/verbal-expressions.svg)](https://www.npmjs.com/package/verbal-expressions)\n[![jsDelivr](https://img.shields.io/badge/dynamic/json.svg?label=jsDelivr&url=https%3A%2F%2Fdata.jsdelivr.com%2Fv1%2Fpackage%2Fnpm%2Fverbal-expressions&query=%24..tags.latest&colorB=blue&prefix=v)](https://www.jsdelivr.com/package/npm/verbal-expressions)\n[![License](https://img.shields.io/github/license/VerbalExpressions/JSVerbalExpressions.svg)](LICENSE)\n\n## JavaScript Regular Expressions made easy\n\nVerbalExpressions is a JavaScript library that helps construct difficult regular expressions.\n\n## How to get started\n\n### In the browser\n\n```html\n<script src=\"VerbalExpressions.js\"></script>\n```\n\nOr use the [jsDelivr CDN](https://www.jsdelivr.com/package/npm/verbal-expressions).\n\n### On the server (node.js)\n\nInstall:\n\n```sh\nnpm install verbal-expressions\n```\n\nRequire:\n\n```js\nconst VerEx = require('verbal-expressions');\n```\n\nOr use ES6's `import`:\n\n```js\nimport VerEx from 'verbal-expressions';\n```\n\n## Running tests\n\n```sh\nnpm test\n```\n\n(or)\n\n```sh\nnpm run test:verbose\n```\n\n## Creating a minified version\n\n```sh\nnpm run build\n```\n\nThis will run [Babel](https://babeljs.io) on `VerbalExpressions.js` and output the result to `dist/verbalexpressions.js`. A minified version of the same will also be written to `dist/verbalexpressions.min.js`.\n\nA source map will also be created in `dist`, so you can use the original \"un-babelified\", unminified source file for debugging purposes.\n\n## Building the docs/ folder\n\nThe `docs/` folder uses Jekyll for building the static HTML and is hosted at\ngh-pages.\n\nTo install the Ruby dependencies, run:\n\n```\ncd docs/\nbundle install\n```\n\nThis installs all needed Ruby dependencies locally\n\nAfter you've installed dependencies, you can run:\n\n```\nbundle exec jekyll build\n```\n\nThis builds all static files to `docs/_site/` folder.\n\nIf you want to develop the files locally, you can run:\n\n```\nbundle exec jekyll serve\n```\n\nThis starts a local development web server and starts watching your files for\nchanges.\n\n## API documentation\n\nYou can find the API documentation at [verbalexpressions.github.io/JSVerbalExpressions](https://verbalexpressions.github.io/JSVerbalExpressions). You can find the source code for the docs in [`docs`](docs/).\n\n## Examples\n\nHere are some simple examples to give an idea of how VerbalExpressions works:\n\n### Testing if we have a valid URL\n\n```js\n// Create an example of how to test for correctly formed URLs\nconst tester = VerEx()\n    .startOfLine()\n    .then('http')\n    .maybe('s')\n    .then('://')\n    .maybe('www.')\n    .anythingBut(' ')\n    .endOfLine();\n\n// Create an example URL\nconst testMe = 'https://www.google.com';\n\n// Use RegExp object's native test() function\nif (tester.test(testMe)) {\n    alert('We have a correct URL'); // This output will fire\n} else {\n    alert('The URL is incorrect');\n}\n\nconsole.log(tester); // Outputs the actual expression used: /^(http)(s)?(\\:\\/\\/)(www\\.)?([^\\ ]*)$/\n```\n\n### Replacing strings\n\n```js\n// Create a test string\nconst replaceMe = 'Replace bird with a duck';\n\n// Create an expression that seeks for word \"bird\"\nconst expression = VerEx().find('bird');\n\n// Execute the expression like a normal RegExp object\nconst result = expression.replace(replaceMe, 'duck');\n\n// Outputs \"Replace duck with a duck\"\nalert(result);\n```\n\n### Shorthand for string replace\n\n```js\nconst result = VerEx().find('red').replace('We have a red house', 'blue');\n\n// Outputs \"We have a blue house\"\nalert(result);\n```\n\n## Contributions\n\nPull requests are warmly welcome!\n\nClone the repo and fork:\n\n```sh\ngit clone https://github.com/VerbalExpressions/JSVerbalExpressions.git\n```\n\n### Style guide\n\nThe [Airbnb](https://github.com/airbnb/javascript) style guide is loosely used as a basis for creating clean and readable JavaScript code. Check [`.eslintrc`](.eslintrc).\n\nCheck out these slide decks for handy Github & git tips:\n\n- [Git and Github Secrets](https://zachholman.com/talk/git-github-secrets/)\n- [More Git and Github Secrets](https://zachholman.com/talk/more-git-and-github-secrets/)\n\n## Tools\n\n- <https://verbalregex.com> - it's a wrapper of JSVerbalExpressions; users can write down the code and compile to regex\n- <https://jsbin.com/metukuzowi/edit?js,console> - JSBin Playground\n\n## Other Implementations\n\nYou can see an up to date list of all ports on [VerbalExpressions.github.io](https://VerbalExpressions.github.io).\n\n- [Ruby](https://github.com/ryan-endacott/verbal_expressions)\n- [C#](https://github.com/VerbalExpressions/CSharpVerbalExpressions)\n- [Python](https://github.com/VerbalExpressions/PythonVerbalExpressions)\n- [Java](https://github.com/VerbalExpressions/JavaVerbalExpressions)\n- [Groovy](https://github.com/VerbalExpressions/GroovyVerbalExpressions)\n- [PHP](https://github.com/VerbalExpressions/PHPVerbalExpressions)\n- [Haskell](https://github.com/VerbalExpressions/HaskellVerbalExpressions)\n- [Haxe](https://github.com/VerbalExpressions/HaxeVerbalExpressions)\n- [C++](https://github.com/VerbalExpressions/CppVerbalExpressions)\n- [Objective-C](https://github.com/VerbalExpressions/ObjectiveCVerbalExpressions)\n- [Perl](https://github.com/VerbalExpressions/PerlVerbalExpressions)\n- [Swift](https://github.com/VerbalExpressions/SwiftVerbalExpressions)\n\nIf you would like to contribute another port (which would be awesome!), please [open an issue](https://github.com/VerbalExpressions/implementation/issues/new) specifying the language in the [VerbalExpressions/implementation repo](https://github.com/VerbalExpressions/implementation/issues). Please don't open PRs for other languages against this repo.\n\n### Similar projects\n\nHere's a list of other similar projects that implement regular expression\nbuilders:\n\n- https://github.com/MaxArt2501/re-build\n- https://github.com/mathiasbynens/regenerate"
  },
  {
    "path": "VerbalExpressions.js",
    "content": "/**\n * @file VerbalExpressions JavaScript Library\n * @version 0.3.0\n * @license MIT\n *\n * @see https://github.com/VerbalExpressions/JSVerbalExpressions\n */\n\n/**\n * Define the VerbalExpression class\n *\n * @class VerbalExpression\n * @extends {RegExp}\n */\nclass VerbalExpression extends RegExp {\n    /**\n     * Creates an instance of VerbalExpression.\n     * @constructor\n     * @alias VerEx\n     * @memberof VerbalExpression\n     */\n    constructor() {\n        // Call the `RegExp` constructor so that `this` can be used\n        super('', 'gm');\n\n        // Variables to hold the expression construction in order\n        this._prefixes = '';\n        this._source = '';\n        this._suffixes = '';\n        this._modifiers = 'gm'; // 'global, multiline' matching by default\n    }\n\n    // Utility //\n\n    /**\n     * Escape meta-characters in the parameter and make it safe for adding to the expression\n     * @static\n     * @param {(string|RegExp|number)} value object to sanitize\n     * @returns {string} sanitized value\n     * @memberof VerbalExpression\n     */\n    static sanitize(value) {\n        if (value instanceof RegExp) {\n            return value.source;\n        }\n\n        if (typeof value === 'number') {\n            return value;\n        }\n\n        if (typeof value !== 'string') {\n            return '';\n        }\n\n        // Regular expression to match meta characters\n        // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp\n        const toEscape = /([\\].|*?+(){}^$\\\\:=[])/g;\n\n        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch\n        const lastMatch = '$&';\n\n        // Escape meta characters\n        return value.replace(toEscape, `\\\\${lastMatch}`);\n    }\n\n    /**\n     * Add stuff to the expression and compile the new expression so it's ready to be used.\n     * @param {(string|number)} [value=''] stuff to add\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    add(value = '') {\n        this._source += value;\n        const pattern = this._prefixes + this._source + this._suffixes;\n\n        this.compile(pattern, this._modifiers);\n\n        return this;\n    }\n\n    // Rules //\n\n    /**\n     * Control start-of-line matching\n     * @param {boolean} [enable=true] whether to enable this behaviour\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    startOfLine(enable = true) {\n        this._prefixes = enable ? '^' : '';\n        return this.add();\n    }\n\n    /**\n     * Control end-of-line matching\n     * @param {boolean} [enable=true] whether to enable this behaviour\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    endOfLine(enable = true) {\n        this._suffixes = enable ? '$' : '';\n        return this.add();\n    }\n\n    /**\n     * Look for the value passed\n     * @param {(string|RegExp|number)} value value to find\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    then(value) {\n        value = VerbalExpression.sanitize(value);\n        return this.add(`(?:${value})`);\n    }\n\n    /**\n     * Alias for then() to allow for readable syntax when then() is the first method in the chain.\n     * @param {(string|RegExp|numer)} value value to find\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    find(value) {\n        return this.then(value);\n    }\n\n    /**\n     * Add optional values\n     * @param {(string|RegExp|number)} value value to find\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    maybe(value) {\n        value = VerbalExpression.sanitize(value);\n        return this.add(`(?:${value})?`);\n    }\n\n    /**\n     * Add alternative expressions\n     * @param {(string|RegExp|number)} value value to find\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    or(value) {\n        this._prefixes += '(?:';\n        this._suffixes = `)${this._suffixes}`;\n\n        this.add(')|(?:');\n\n        if (value) {\n            this.then(value);\n        }\n\n        return this;\n    }\n\n    /**\n     * Any character any number of times\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    anything() {\n        return this.add('(?:.*)');\n    }\n\n    /**\n     * Anything but these characters\n     * @param {(string|number|string[]|number[])} value characters to not match\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    anythingBut(value) {\n        if (Array.isArray(value)) {\n            value = value.join('');\n        }\n\n        value = VerbalExpression.sanitize(value);\n        return this.add(`(?:[^${value}]*)`);\n    }\n\n    /**\n     * Any character(s) at least once\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    something() {\n        return this.add('(?:.+)');\n    }\n\n    /**\n     * Any character at least one time except for these characters\n     * @param {(string|number|string[]|number[])} value characters to not match\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    somethingBut(value) {\n        if (Array.isArray(value)) {\n            value = value.join('');\n        }\n\n        value = VerbalExpression.sanitize(value);\n        return this.add(`(?:[^${value}]+)`);\n    }\n\n    /**\n     * Match any of the given characters\n     * @param {(string|number|string[]|number[])} value characters to match\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    anyOf(value) {\n        if (Array.isArray(value)) {\n            value = value.join('');\n        }\n\n        value = VerbalExpression.sanitize(value);\n        return this.add(`[${value}]`);\n    }\n\n    /**\n     * Shorthand for anyOf(value)\n     * @param {string|number} value value to find\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    any(value) {\n        return this.anyOf(value);\n    }\n\n    /**\n     * Ensure that the parameter does not follow\n     * @param {string|number} value\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    not(value) {\n        value = VerbalExpression.sanitize(value);\n        this.add(`(?!${value})`);\n\n        return this;\n    }\n\n    /**\n     * Matching any character within a range of characters\n     * Usage: .range( from, to [, from, to ... ] )\n     * @param {...string} ranges characters denoting beginning and ending of ranges\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    range(...ranges) {\n        let value = '';\n\n        for (let i = 1; i < ranges.length; i += 2) {\n            const from = VerbalExpression.sanitize(ranges[i - 1]);\n            const to = VerbalExpression.sanitize(ranges[i]);\n\n            value += `${from}-${to}`;\n        }\n\n        return this.add(`[${value}]`);\n    }\n\n    // Special characters //\n\n    /**\n     * Match a Line break\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    lineBreak() {\n        return this.add('(?:\\\\r\\\\n|\\\\r|\\\\n)'); // Unix(LF) + Windows(CRLF)\n    }\n\n    /**\n     * A shorthand for lineBreak() for html-minded users\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    br() {\n        return this.lineBreak();\n    }\n\n    /**\n     * Match a tab character\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    tab() {\n        return this.add('\\\\t');\n    }\n\n    /**\n     * Match any alphanumeric\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    word() {\n        return this.add('\\\\w+');\n    }\n\n    /**\n     * Match a single digit\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    digit() {\n        return this.add('\\\\d');\n    }\n\n    /**\n     * Match a single whitespace\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    whitespace() {\n        return this.add('\\\\s');\n    }\n\n    // Modifiers //\n\n    /**\n     * Add a regex modifier/flag\n     * @param {string} modifier modifier to add\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    addModifier(modifier) {\n        if (!this._modifiers.includes(modifier)) {\n            this._modifiers += modifier;\n        }\n\n        return this.add();\n    }\n\n    /**\n     * Remove modifier\n     * @param {string} modifier modifier to remove\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    removeModifier(modifier) {\n        this._modifiers = this._modifiers.replace(modifier, '');\n        return this.add();\n    }\n\n    /**\n     * Control case-insensitive matching\n     * @param {boolean} [enable=true] whether to enable this behaviour\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    withAnyCase(enable = true) {\n        return enable ? this.addModifier('i') : this.removeModifier('i');\n    }\n\n    /**\n     * Default behaviour is with \"g\" modifier, so we can turn this another way around than other modifiers\n     * @param {boolean} [enable=true] whether to enable this behaviour\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    stopAtFirst(enable = true) {\n        return enable ? this.removeModifier('g') : this.addModifier('g');\n    }\n\n    /**\n     * Control the multiline modifier\n     * @param {boolean} [enable=true] whether to enable this behaviour\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    searchOneLine(enable = true) {\n        return enable ? this.removeModifier('m') : this.addModifier('m');\n    }\n\n    // Loops //\n\n    /**\n     * Repeat the previous item exactly n times or between n and m times\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    repeatPrevious(...quantity) {\n        const isInteger = /\\d+/;\n        const values = quantity.filter((argument) => isInteger.test(argument));\n\n        if (values.length === 0 || values.length > 2) {\n            return this;\n        }\n\n        this.add(`{${values.join(',')}}`);\n\n        return this;\n    }\n\n    /**\n     * Repeat the previous at least once\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    oneOrMore() {\n        return this.add('+');\n    }\n\n    /**\n     * Match the value zero or more times\n     * @param {string} value value to find\n     * @param {integer} [lower] minimum number of times the value should be repeated\n     * @param {integer} [upper] maximum number of times the value should be repeated\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    multiple(value, lower, upper) {\n        if (value !== undefined) {\n            value = VerbalExpression.sanitize(value);\n            this.add(`(?:${value})`);\n        }\n\n        if (lower === undefined && upper === undefined) {\n            this.add('*'); // Any number of times\n        } else if (lower !== undefined && upper === undefined) {\n            this.add(`{${lower},}`);\n        } else if (lower !== undefined && upper !== undefined) {\n            this.add(`{${lower},${upper}}`);\n        }\n\n        return this;\n    }\n\n    // Capture groups //\n\n    /**\n     * Starts a capturing group\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    beginCapture() {\n        // Add the end of the capture group to the suffixes temporarily so that compilation continues to work\n        this._suffixes += ')';\n        return this.add('(');\n    }\n\n    /**\n     * Ends a capturing group\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    endCapture() {\n        // Remove the last parenthesis from the _suffixes and add it to the regex\n        this._suffixes = this._suffixes.slice(0, -1);\n        return this.add(')');\n    }\n\n    // Miscellaneous //\n\n    /**\n     * Shorthand function for the string.replace function to allow for a more logical flow\n     * @param {string} source string to search for\n     * @param {string} value value to replace with\n     * @returns {VerbalExpression} recompiled instance of VerbalExpression\n     * @memberof VerbalExpression\n     */\n    replace(source, value) {\n        source = source.toString();\n        return source.replace(this, value);\n    }\n\n    /**\n     * Convert to RegExp object\n     * @returns {RegExp} equivalent RegExp instance\n     * @memberof VerbalExpression\n     */\n    toRegExp() {\n        const components = this.toString().match(/\\/(.*)\\/([gimuy]+)?/);\n        const pattern = components[1];\n        const flags = components[2];\n\n        return new RegExp(pattern, flags);\n    }\n}\n\n/**\n * Return a new instance of `VerbalExpression`\n * @export\n * @returns {VerbalExpression} new instance\n */\nfunction VerEx() { // eslint-disable-line no-unused-vars\n    const instance = new VerbalExpression();\n    instance.sanitize = VerbalExpression.sanitize;\n    return instance;\n}\n"
  },
  {
    "path": "bower.json",
    "content": "{\n    \"name\": \"verbal-expressions\",\n    \"description\": \"JavaScript Regular expressions made easy\",\n    \"keywords\": [ \"regular expressions\", \"regex\" ],\n    \"main\": \"dist/verbalexpressions.js\",\n    \"license\": \"MIT\",\n    \"ignore\": [\n        \"**/.*\",\n        \"node_modules\",\n        \"bower_components\",\n        \"test\",\n        \"tests\",\n        \"Gruntfile.js\",\n        \"package.json\",\n        \"bower.json\"\n    ]\n}\n"
  },
  {
    "path": "dist/verbalexpressions.js",
    "content": "(function (root, factory) {\n  if (root === undefined && window !== undefined) root = window;\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define('VerEx', [], function () {\n      return (root['VerEx'] = factory());\n    });\n  } else if (typeof module === 'object' && module.exports) {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    root['VerEx'] = factory();\n  }\n}(this, function () {\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _extendableBuiltin(cls) {\n    function ExtendableBuiltin() {\n        var instance = Reflect.construct(cls, Array.from(arguments));\n        Object.setPrototypeOf(instance, Object.getPrototypeOf(this));\n        return instance;\n    }\n\n    ExtendableBuiltin.prototype = Object.create(cls.prototype, {\n        constructor: {\n            value: cls,\n            enumerable: false,\n            writable: true,\n            configurable: true\n        }\n    });\n\n    if (Object.setPrototypeOf) {\n        Object.setPrototypeOf(ExtendableBuiltin, cls);\n    } else {\n        ExtendableBuiltin.__proto__ = cls;\n    }\n\n    return ExtendableBuiltin;\n}\n\n/**\n * @file VerbalExpressions JavaScript Library\n * @version 0.3.0\n * @license MIT\n *\n * @see https://github.com/VerbalExpressions/JSVerbalExpressions\n */\n\n/**\n * Define the VerbalExpression class\n *\n * @class VerbalExpression\n * @extends {RegExp}\n */\nvar VerbalExpression = function (_extendableBuiltin2) {\n    _inherits(VerbalExpression, _extendableBuiltin2);\n\n    /**\n     * Creates an instance of VerbalExpression.\n     * @constructor\n     * @alias VerEx\n     * @memberof VerbalExpression\n     */\n    function VerbalExpression() {\n        _classCallCheck(this, VerbalExpression);\n\n        // Variables to hold the expression construction in order\n        var _this = _possibleConstructorReturn(this, (VerbalExpression.__proto__ || Object.getPrototypeOf(VerbalExpression)).call(this, '', 'gm'));\n        // Call the `RegExp` constructor so that `this` can be used\n\n\n        _this._prefixes = '';\n        _this._source = '';\n        _this._suffixes = '';\n        _this._modifiers = 'gm'; // 'global, multiline' matching by default\n        return _this;\n    }\n\n    // Utility //\n\n    /**\n     * Escape meta-characters in the parameter and make it safe for adding to the expression\n     * @static\n     * @param {(string|RegExp|number)} value object to sanitize\n     * @returns {string} sanitized value\n     * @memberof VerbalExpression\n     */\n\n\n    _createClass(VerbalExpression, [{\n        key: 'add',\n\n\n        /**\n         * Add stuff to the expression and compile the new expression so it's ready to be used.\n         * @param {(string|number)} [value=''] stuff to add\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n        value: function add() {\n            var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';\n\n            this._source += value;\n            var pattern = this._prefixes + this._source + this._suffixes;\n\n            this.compile(pattern, this._modifiers);\n\n            return this;\n        }\n\n        // Rules //\n\n        /**\n         * Control start-of-line matching\n         * @param {boolean} [enable=true] whether to enable this behaviour\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'startOfLine',\n        value: function startOfLine() {\n            var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n            this._prefixes = enable ? '^' : '';\n            return this.add();\n        }\n\n        /**\n         * Control end-of-line matching\n         * @param {boolean} [enable=true] whether to enable this behaviour\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'endOfLine',\n        value: function endOfLine() {\n            var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n            this._suffixes = enable ? '$' : '';\n            return this.add();\n        }\n\n        /**\n         * Look for the value passed\n         * @param {(string|RegExp|number)} value value to find\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'then',\n        value: function then(value) {\n            value = VerbalExpression.sanitize(value);\n            return this.add('(?:' + value + ')');\n        }\n\n        /**\n         * Alias for then() to allow for readable syntax when then() is the first method in the chain.\n         * @param {(string|RegExp|numer)} value value to find\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'find',\n        value: function find(value) {\n            return this.then(value);\n        }\n\n        /**\n         * Add optional values\n         * @param {(string|RegExp|number)} value value to find\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'maybe',\n        value: function maybe(value) {\n            value = VerbalExpression.sanitize(value);\n            return this.add('(?:' + value + ')?');\n        }\n\n        /**\n         * Add alternative expressions\n         * @param {(string|RegExp|number)} value value to find\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'or',\n        value: function or(value) {\n            this._prefixes += '(?:';\n            this._suffixes = ')' + this._suffixes;\n\n            this.add(')|(?:');\n\n            if (value) {\n                this.then(value);\n            }\n\n            return this;\n        }\n\n        /**\n         * Any character any number of times\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'anything',\n        value: function anything() {\n            return this.add('(?:.*)');\n        }\n\n        /**\n         * Anything but these characters\n         * @param {(string|number|string[]|number[])} value characters to not match\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'anythingBut',\n        value: function anythingBut(value) {\n            if (Array.isArray(value)) {\n                value = value.join('');\n            }\n\n            value = VerbalExpression.sanitize(value);\n            return this.add('(?:[^' + value + ']*)');\n        }\n\n        /**\n         * Any character(s) at least once\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'something',\n        value: function something() {\n            return this.add('(?:.+)');\n        }\n\n        /**\n         * Any character at least one time except for these characters\n         * @param {(string|number|string[]|number[])} value characters to not match\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'somethingBut',\n        value: function somethingBut(value) {\n            if (Array.isArray(value)) {\n                value = value.join('');\n            }\n\n            value = VerbalExpression.sanitize(value);\n            return this.add('(?:[^' + value + ']+)');\n        }\n\n        /**\n         * Match any of the given characters\n         * @param {(string|number|string[]|number[])} value characters to match\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'anyOf',\n        value: function anyOf(value) {\n            if (Array.isArray(value)) {\n                value = value.join('');\n            }\n\n            value = VerbalExpression.sanitize(value);\n            return this.add('[' + value + ']');\n        }\n\n        /**\n         * Shorthand for anyOf(value)\n         * @param {string|number} value value to find\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'any',\n        value: function any(value) {\n            return this.anyOf(value);\n        }\n\n        /**\n         * Ensure that the parameter does not follow\n         * @param {string|number} value\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'not',\n        value: function not(value) {\n            value = VerbalExpression.sanitize(value);\n            this.add('(?!' + value + ')');\n\n            return this;\n        }\n\n        /**\n         * Matching any character within a range of characters\n         * Usage: .range( from, to [, from, to ... ] )\n         * @param {...string} ranges characters denoting beginning and ending of ranges\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'range',\n        value: function range() {\n            var value = '';\n\n            for (var i = 1; i < arguments.length; i += 2) {\n                var from = VerbalExpression.sanitize(arguments.length <= i - 1 ? undefined : arguments[i - 1]);\n                var to = VerbalExpression.sanitize(arguments.length <= i ? undefined : arguments[i]);\n\n                value += from + '-' + to;\n            }\n\n            return this.add('[' + value + ']');\n        }\n\n        // Special characters //\n\n        /**\n         * Match a Line break\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'lineBreak',\n        value: function lineBreak() {\n            return this.add('(?:\\\\r\\\\n|\\\\r|\\\\n)'); // Unix(LF) + Windows(CRLF)\n        }\n\n        /**\n         * A shorthand for lineBreak() for html-minded users\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'br',\n        value: function br() {\n            return this.lineBreak();\n        }\n\n        /**\n         * Match a tab character\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'tab',\n        value: function tab() {\n            return this.add('\\\\t');\n        }\n\n        /**\n         * Match any alphanumeric\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'word',\n        value: function word() {\n            return this.add('\\\\w+');\n        }\n\n        /**\n         * Match a single digit\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'digit',\n        value: function digit() {\n            return this.add('\\\\d');\n        }\n\n        /**\n         * Match a single whitespace\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'whitespace',\n        value: function whitespace() {\n            return this.add('\\\\s');\n        }\n\n        // Modifiers //\n\n        /**\n         * Add a regex modifier/flag\n         * @param {string} modifier modifier to add\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'addModifier',\n        value: function addModifier(modifier) {\n            if (!this._modifiers.includes(modifier)) {\n                this._modifiers += modifier;\n            }\n\n            return this.add();\n        }\n\n        /**\n         * Remove modifier\n         * @param {string} modifier modifier to remove\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'removeModifier',\n        value: function removeModifier(modifier) {\n            this._modifiers = this._modifiers.replace(modifier, '');\n            return this.add();\n        }\n\n        /**\n         * Control case-insensitive matching\n         * @param {boolean} [enable=true] whether to enable this behaviour\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'withAnyCase',\n        value: function withAnyCase() {\n            var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n            return enable ? this.addModifier('i') : this.removeModifier('i');\n        }\n\n        /**\n         * Default behaviour is with \"g\" modifier, so we can turn this another way around than other modifiers\n         * @param {boolean} [enable=true] whether to enable this behaviour\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'stopAtFirst',\n        value: function stopAtFirst() {\n            var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n            return enable ? this.removeModifier('g') : this.addModifier('g');\n        }\n\n        /**\n         * Control the multiline modifier\n         * @param {boolean} [enable=true] whether to enable this behaviour\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'searchOneLine',\n        value: function searchOneLine() {\n            var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n            return enable ? this.removeModifier('m') : this.addModifier('m');\n        }\n\n        // Loops //\n\n        /**\n         * Repeat the previous item exactly n times or between n and m times\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'repeatPrevious',\n        value: function repeatPrevious() {\n            var isInteger = /\\d+/;\n\n            for (var _len = arguments.length, quantity = Array(_len), _key = 0; _key < _len; _key++) {\n                quantity[_key] = arguments[_key];\n            }\n\n            var values = quantity.filter(function (argument) {\n                return isInteger.test(argument);\n            });\n\n            if (values.length === 0 || values.length > 2) {\n                return this;\n            }\n\n            this.add('{' + values.join(',') + '}');\n\n            return this;\n        }\n\n        /**\n         * Repeat the previous at least once\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'oneOrMore',\n        value: function oneOrMore() {\n            return this.add('+');\n        }\n\n        /**\n         * Match the value zero or more times\n         * @param {string} value value to find\n         * @param {integer} [lower] minimum number of times the value should be repeated\n         * @param {integer} [upper] maximum number of times the value should be repeated\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'multiple',\n        value: function multiple(value, lower, upper) {\n            if (value !== undefined) {\n                value = VerbalExpression.sanitize(value);\n                this.add('(?:' + value + ')');\n            }\n\n            if (lower === undefined && upper === undefined) {\n                this.add('*'); // Any number of times\n            } else if (lower !== undefined && upper === undefined) {\n                this.add('{' + lower + ',}');\n            } else if (lower !== undefined && upper !== undefined) {\n                this.add('{' + lower + ',' + upper + '}');\n            }\n\n            return this;\n        }\n\n        // Capture groups //\n\n        /**\n         * Starts a capturing group\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'beginCapture',\n        value: function beginCapture() {\n            // Add the end of the capture group to the suffixes temporarily so that compilation continues to work\n            this._suffixes += ')';\n            return this.add('(');\n        }\n\n        /**\n         * Ends a capturing group\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'endCapture',\n        value: function endCapture() {\n            // Remove the last parenthesis from the _suffixes and add it to the regex\n            this._suffixes = this._suffixes.slice(0, -1);\n            return this.add(')');\n        }\n\n        // Miscellaneous //\n\n        /**\n         * Shorthand function for the string.replace function to allow for a more logical flow\n         * @param {string} source string to search for\n         * @param {string} value value to replace with\n         * @returns {VerbalExpression} recompiled instance of VerbalExpression\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'replace',\n        value: function replace(source, value) {\n            source = source.toString();\n            return source.replace(this, value);\n        }\n\n        /**\n         * Convert to RegExp object\n         * @returns {RegExp} equivalent RegExp instance\n         * @memberof VerbalExpression\n         */\n\n    }, {\n        key: 'toRegExp',\n        value: function toRegExp() {\n            var components = this.toString().match(/\\/(.*)\\/([gimuy]+)?/);\n            var pattern = components[1];\n            var flags = components[2];\n\n            return new RegExp(pattern, flags);\n        }\n    }], [{\n        key: 'sanitize',\n        value: function sanitize(value) {\n            if (value instanceof RegExp) {\n                return value.source;\n            }\n\n            if (typeof value === 'number') {\n                return value;\n            }\n\n            if (typeof value !== 'string') {\n                return '';\n            }\n\n            // Regular expression to match meta characters\n            // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp\n            var toEscape = /([\\].|*?+(){}^$\\\\:=[])/g;\n\n            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch\n            var lastMatch = '$&';\n\n            // Escape meta characters\n            return value.replace(toEscape, '\\\\' + lastMatch);\n        }\n    }]);\n\n    return VerbalExpression;\n}(_extendableBuiltin(RegExp));\n\n/**\n * Return a new instance of `VerbalExpression`\n * @export\n * @returns {VerbalExpression} new instance\n */\n\n\nfunction VerEx() {\n    // eslint-disable-line no-unused-vars\n    var instance = new VerbalExpression();\n    instance.sanitize = VerbalExpression.sanitize;\n    return instance;\n}\n//# sourceMappingURL=verbalexpressions.js.map\n\nreturn VerEx;\n\n}));\n"
  },
  {
    "path": "docs/404.md",
    "content": "# Page not found\n\nPerhaps you wish to go to the [home page](/) instead?\n"
  },
  {
    "path": "docs/Gemfile",
    "content": "source \"https://rubygems.org\"\n\ngem \"github-pages\", group: :jekyll_plugins\n\n"
  },
  {
    "path": "docs/VerEx.md",
    "content": "# `VerEx`\n\nReturn a new instance of [`VerbalExpression`](VerbalExpression).\n\nThis is the function that is exported from within `VerbalExpressions.js` and is to be the first method in chains that describe verbal expressions.\n"
  },
  {
    "path": "docs/VerbalExpression/capture-groups.md",
    "content": "# Capture Groups\n\nCapture groups are used to extract data from within the regular expression match for further processing.\n\n## `beginCapture`\n\nBegin a capture group.\n\n## `endCapture`\n\nEnd a capture group.\n\n___\n\n```js\nconst phoneNumber = VerEx()\n    .find('+')\n    .beginCapture()\n        .digit().repeatPrevious(2)\n    .endCapture()\n    .then('-')\n    .digit().repeatPrevious(10);\n\nconst [, countryCode] = phoneNumber.exec('+91-2223387510');\nconsole.log(countryCode); // => '91'\n```\n"
  },
  {
    "path": "docs/VerbalExpression/constructor.md",
    "content": "# Constructor\n\n## `constructor`\n\nConstruct and return a new instance of [`VerbalExpression`](#verbalexpression). Used to support the `new VerbalExpression()` syntax in ES6 classes as mandated by [the spec](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/constructor). You usually wouldn't need to call `VerEx().constructor()`.\n"
  },
  {
    "path": "docs/VerbalExpression/index.md",
    "content": "---\ntitle: VerbalExpression\n---\n\n# `VerbalExpression`\n\nA class that extends [`RegExp`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) and wraps all VerbalExpressions functionality.\n\n## Table of Contents\n\n- [Constructor](../VerbalExpression/constructor)\n    - [`constructor`](../VerbalExpression/constructor#constructor)\n- [Utilities](../VerbalExpression/utilities)\n    - [`static sanitize`](../VerbalExpression/utilities#static)\n    - [`add`](../VerbalExpression/utilities#add)\n- [Rules](../VerbalExpression/rules)\n    - [`startOfLine`](../VerbalExpression/rules#startOfLine)\n    - [`endOfLine`](../VerbalExpression/rules#endOfLine)\n    - [`then`](../VerbalExpression/rules#then)\n    - [`find`](../VerbalExpression/rules#find)\n    - [`maybe`](../VerbalExpression/rules#maybe)\n    - [`or`](../VerbalExpression/rules#or)\n    - [`anything`](../VerbalExpression/rules#anything)\n    - [`anythingBut`](../VerbalExpression/rules#anythingBut)\n    - [`something`](../VerbalExpression/rules#something)\n    - [`somethingBut`](../VerbalExpression/rules#somethingBut)\n    - [`anyOf`](../VerbalExpression/rules#anyOf)\n    - [`any`](../VerbalExpression/rules#any)\n    - [`not`](../VerbalExpression/rules#not)\n    - [`range`](../VerbalExpression/rules#range)\n- [Special Characters](../VerbalExpression/special-characters)\n    - [`lineBreak`](../VerbalExpression/special-characters#lineBreak)\n    - [`br`](../VerbalExpression/special-characters#br)\n    - [`tab`](../VerbalExpression/special-characters#tab)\n    - [`word`](../VerbalExpression/special-characters#word)\n    - [`digit`](../VerbalExpression/special-characters#digit)\n    - [`whitespace`](../VerbalExpression/special-characters#whitespace)\n- [Modifiers](../VerbalExpression/modifiers)\n    - [`addModifier`](../VerbalExpression/modifiers#addModifier)\n    - [`removeModifier`](../VerbalExpression/modifiers#removeModifier)\n    - [`withAnyCase`](../VerbalExpression/modifiers#withAnyCase)\n    - [`stopAtFirst`](../VerbalExpression/modifiers#stopAtFirst)\n    - [`searchOneLine`](../VerbalExpression/modifiers#searchOneLine)\n    - [`repeatPrevious`](../VerbalExpression/modifiers#repeatPrevious)\n- [Loops](../VerbalExpression/loops)\n    - [`oneOrMore`](../VerbalExpression/loops#oneOrMore)\n    - [`multiple`](../VerbalExpression/loops#multiple)\n- [Capture Groups](../VerbalExpression/capture-groups)\n    - [`beginCapture`](../VerbalExpression/capture-groups#beginCapture)\n    - [`endCapture`](../VerbalExpression/capture-groups#endCapture)\n- [Miscellaneous](../VerbalExpression/miscellaneous)\n    - [`replace`](../VerbalExpression/miscellaneous#replace)\n    - [`toRegExp`](../VerbalExpression/miscellaneous#toRegExp)\n"
  },
  {
    "path": "docs/VerbalExpression/loops.md",
    "content": "# Loops\n\n## `oneOrMore`\n\nMatch the previous stuff one or more times.\n\n```js\nconst integer = VerEx().digit().oneOrMore();\nconsole.log(integer.exec('foo 12345')[0]); // => '12345'\n```\n\n## `multiple`\n\n### Usage 1\n\nMatch the previous group any number of times.\n\n```js\nconst expr = VerEx().startOfLine().find(' ').multiple().endOfLine();\n\nconsole.log(expr.test('   ')); // => true\n```\n\n### Usage 2\n\nMatch something zero or more times.\n\nParameter | Expected type | Description\n----------|---------------|--------------\n`value`   | `String`      | Item to match\n\n```js\nconst expr = VerEx()\n    .find('what').multiple('?')\n    .endOfLine();\n\nconsole.log(expr.test('what')); // => true\nexpr.lastIndex = 0;\nconsole.log(expr.test('what???'));// => true\n```\n\n### Usage 3\n\nMatch something greater than or equal to `min` number of times.\n\nParameter | Expected type | Description\n----------|---------------|---------------------------------------------\n`value`   | `String`      | Item to match\n`min`     | `Number`      | Minimum number of times it should be present\n\n```js\nconst expr = VerEx()\n    .find('hurray').then('!').multiple(1)\n    .endOfLine();\n\nconsole.log(expr.test('hurray')); // => false\nexpr.lastIndex = 0;\nconsole.log(expr.test('hurray!!')); // => true\n```\n\n### Usage 4\n\nMatch something between `min` and `max` (inclusive) number of times.\n\nParameter | Expected type | Description\n----------|---------------|---------------------------------------------\n`value`   | `String`      | Item to match\n`min`     | `Number`      | Minimum number of times it should be present\n`max`     | `Number`      | Maximum number of times it should be present\n\n```js\nconst expr = VerEx()\n    .find('h').then('i').multiple(1, 3)\n    .endOfLine();\n\nconsole.log(expr.test('hiii')); // => true\nexpr.lastIndex = 0;\nconsole.log(expr.test('hiiii')); // => false\n```\n"
  },
  {
    "path": "docs/VerbalExpression/miscellaneous.md",
    "content": "# Miscellaneous\n\n## `replace`\n\nReplace characters matching the VerbalExpression in a string with another string.\n\nParameter | Expected type | Description\n----------|---------------|-------------------------------\n`source`  | `String`      | String to look for matches in\n`value`   | `String`      | String to replace matches with\n\nReturn type: [`String`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)\n\n```js\nconst spaces = VerEx().find(' ');\nconst fileName = 'a file name.txt';\n\n// => 'a_file_name.txt'\nconsole.log(spaces.replace(fileName, '_'));\n```\n\n## `toRegExp`\n\nConvert the class to a [`RegExp`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) object.\n\nReturn type: [`RegExp`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp)\n\n```js\nconst expr = VerEx().find('foo');\nconsole.log(expr.toRegExp()); // => /(?:foo)/gm\n```\n"
  },
  {
    "path": "docs/VerbalExpression/modifiers.md",
    "content": "# Modifiers\n\n## `addModifier`\n\nManually add a regex modifier (flag).\n\nParameter | Expected type | Description\n----------|---------------|----------------\n`value`   | `String`      | Modifier to add\n\n```js\nlet expr = VerEx()\nconsole.log(expr.flags); // => 'gm'\n\nexpr = expr.addModifier('i');\nconsole.log(expr.flags); // => 'gim'\n```\n\n## `removeModifier`\n\nManually remove a regex modifier (flag).\n\nParameter | Expected type | Description\n----------|---------------|-------------------\n`value`   | `String`      | Modifier to remove\n\n```js\nlet expr = VerEx();\nconsole.log(expr.flags); // => 'gm'\n\nexpr = expr.removeModifier('m');\nconsole.log(expr.flags); // => 'g'\n```\n\n## `withAnyCase`\n\nControl case-insensitive matching. Equivalent to adding or removing the `i` modifier.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`enable` (defaults to `true`) | `boolean` | Whether to enable this behavior\n\n```js\nconst hexColorCode = VerEx()\n    .find('#')\n    .range('0', '9', 'a', 'f')\n    .repeatPrevious(6)\n    .withAnyCase();\n\nconsole.log(hexColorCode.test('#93afee')); // => true\nhexColorCode.lastIndex = 0;\nconsole.log(hexColorCode.test('#93AFEE')); // => true\n```\n\n## `stopAtFirst`\n\nControl global matching. Enabling would cause the expression to not look for matches beyond the first match. Equivalent to removing or adding the `g` modifier. Global matching is enabled by default.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`enable` (defaults to `true`) | `boolean` | Whether to enable this behavior\n\n```js\n```\n\n## `searchOneLine`\n\nControl multi-line matching. Enabling would cause the expression to not look for matches beyond the first line. Equivalent to removing or adding the `m` modifier. Multi-line matching is enabled by default.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`enable` (defaults to `true`) | `boolean` | Whether to enable this behavior\n\n```js\nlet findFoo = VerEx().startOfLine().find('foo').endOfLine();\nconsole.log(findFoo.test('foo\\nfoo\\nfoo')); // => true\n\nfindFoo = findFoo.searchOneLine();\nconsole.log(findFoo.test('foo\\nfoo\\nfoo')); // => false\n```\n\n## `repeatPrevious`\n\n### Usage 1\n\nRepeat the previous item exactly `count` times.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`count`   | `Number`      | Number of times to repeat the previous item\n\n```js\nconst expr = VerEx()\n    .startOfLine()\n    .find('foo')\n    .repeatPrevious(2)\n    .endOfLine();\n\nconsole.log(expr.test('foofoo')); // => true\nexpr.lastIndex = 0;\nconsole.log(expr.test('foofoofoo')); // => false\n```\n\n### Usage 2\n\nRepeat the previous item between `mix` and `max` (inclusive) times.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`min`     | `Number`      | Minimum number of times to repeat the previous item\n`max`     | `Number`      | Maximum number of times to repeat the previous item\n\n```js\nconst expr = VerEx()\n    .startOfLine()\n    .find('foo')\n    .repeatPrevious(1, 3)\n    .endOfLine();\n\nconsole.log(expr.test('foo')); // => true\nexpr.lastIndex = 0;\nconsole.log(expr.test('foofoo')); // => true\nexpr.lastIndex = 0;\nconsole.log(expr.test('foofoofoo')); // => true\nexpr.lastIndex = 0;\nconsole.log(expr.test('foofoofoofoo')); // => false\n```\n"
  },
  {
    "path": "docs/VerbalExpression/rules.md",
    "content": "# Rules\n\n## `startOfLine`\n\nControl whether to match the expression only if it appears from the beginning of the line.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`enable` (defaults to `true`)  | `boolean` | Whether to enable this behavior\n\n```js\nconst expr1 = VerEx().find('apple');\nconsole.log(expr1.test('pineapple')); // => true\n\nconst expr2 = VerEx().startOfLine().find('apple');\nconsole.log(expr2.test('pineapple')); // => false\n```\n\n## `endOfLine`\n\nControl whether to match the expression only if it appears till the end of the line.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`enable` (defaults to `true`)  | `boolean` | Whether to enable this behavior\n\n```js\nconst expr1 = VerEx().find('apple');\nconsole.log(expr1.test('apples')); // => true\n\nconst expr2 = VerEx().find('apple').endOfLine();\nconsole.log(expr2.test('apples')); // => false\n```\n\n## `then`\n\nMatch an expression.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`value`   | `String`, `number`, `RegExp`, `VerbalExpression` | Expression to match\n\n```js\nconst expr = VerEx().then('foo');\nconsole.log(expr.test('foo')); // => true\n```\n\n## `find`\n\nAlias for [`then`](#then). Meant for semantics when used at the beginning of a verbal expression. For example, `VerEx().find('foo')` is more readable than `VerEx().then('foo')`.\n\n## `maybe`\n\nOptionally match an expression.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`value`   | `String`, `number`, `RegExp`, `VerbalExpression` | Expression to optionally match\n\n```js\nconst protocol = VerEx().find('http').maybe('s').then('://');\n\nconsole.log(protocol.test('http://')); // => true\nprotocol.lastIndex = 0;\nconsole.log(protocol.test('https://')); // => true\n```\n\n## `or`\n\nAlternatively, match another expression.\n\nParameter | Expected type | Description\n----------|---------------|------------\n`value` (optional)  | `String`, `number`, `RegExp`, `VerbalExpression` | Expression to match instead\n\nIf no parameters are passed into `or`, the alternate expression would be the one built after the call to `or`.\n\n```js\nlet fooOrBar = VerEx().find('foo').or('bar');\nconsole.log(expr.test('foo')); // => true\nfooOrBar.lastIndex = 0\nconsole.log(expr.test('bar')); // => true\n\n// alternate syntax\nfooOrBar = VerEx().find('foo').or().find('bar');\nconsole.log(expr.test('foo')); // => true\nfooOrBar.lastIndex = 0\nconsole.log(expr.test('bar')); // => true\n```\n\n## `anything`\n\nMatch any character(s) any (including zero) number of times.\n\n```js\nconst anything = VerEx().anything();\n\nconsole.log(anything.test('')); // => true\nanything.lastIndex = 0;\nconsole.log(anything.test('x')); // => true\n```\n\n## `anythingBut`\n\nMatch any character(s) except these any (including zero) number of times.\n\nParameter | Expected type        | Description\n----------|----------------------|------------------------\n`value`   | `String`, `[String]` | Characters to not match\n\n```js\nconst anythingButXyz = VerEx().anythingBut('xyz');\n\nconsole.log(anythingButXyz.test('')); // => true\nanythingButXyz.lastIndex = 0;\nconsole.log(anythingButXyz.test('a')); // => true\nanythingButXyz.lastIndex = 0;\nconsole.log(anythingButXyz.test('x')); // => false\n```\n\n## `something`\n\nMatch any character(s) at least once.\n\n```js\nconst something = VerEx().something();\n\nconsole.log(something.test('abc')); // => true\nsomething.lastIndex = 0;\nconsole.log(something.test('')); // => false\n```\n\n## `somethingBut`\n\nMatch any character(s) except these at least once.\n\nParameter | Expected type        | Description\n----------|----------------------|------------------------\n`value`   | `String`, `[String]` | Characters to not match\n\n```js\nconst somethingButXyz = VerEx().somethingBut('xyz');\n\nconsole.log(somethingButXyz.test('abc')); // => true\nsomethingButXyz.lastIndex = 0;\nconsole.log(somethingButXyz.test('')); // => false\nsomethingButXyz.lastIndex = 0;\nconsole.log(somethingButXyz.test('xyz')); // => false\n```\n\n## `anyOf`\n\nMatch any of these characters exactly once.\n\nParameter | Expected type         | Description\n----------|-----------------------|--------------------\n`value`   | `String`,  `[String]` | Characters to match\n\n```js\nconst expr = VerEx().anyOf('abc');\nconsole.log(expr.test('c')); // => true\nexpr.lastIndex = 0;\nconsole.log(expr.test('d')); // => false\n```\n\n## `any`\n\nAlias for [`anyOf`](#anyof).\n\n## `not`\n\nEnsure that the parameter does not follow.\n\nParameter | Expected type   | Description\n----------|-----------------|---------------------------\n`value`   | `String|Number` | Value to ensure absence of\n\n```js\nconst notLeapDay = VerEx().startOfLine()not('FEB-29').something().endOfLine();\n\nconsole.log(notLeapDay.test('FEB-29-2017')); // => false\nnotLeapDay.lastIndex = 0;\nconsole.log(notLeapDay.test('FEB-28-2017')); // => true\n```\n\n## `range`\n\nMatch any character within the range defined by the parameters.\n\nParameter  | Expected type | Description\n-----------|---------------|--------------------\n`...range` | `String[]`    | Range of characters\n\nArguments will be interpreted as pairs.\n\nFor example, `.range('a', 'z', '0', '9')` will be interpreted to mean any character within the ranges `a–z` (ascii x–y) or `0–9` (ascii x–y). The method expects an even number of parameters; unpaired parameters are ignored.\n\n```js\nconst hex = VerEx().range('0', '9', 'a', 'f').oneOrMore();\n\nconsole.log(hex.test('b39a3f')); // => true\nhex.lastIndex = 0;\nconsole.log(hex.test('b39aeg')); // => false\n```\n"
  },
  {
    "path": "docs/VerbalExpression/special-characters.md",
    "content": "# Special Characters\n\n## `lineBreak`\n\nMatch a line break (both [Unix style](//codepoints.net/U+000A) and [Windows style](//codepoints.net/U+000D)).\n\n```js\nconst expr = VerEx().find('foo').lineBreak().then('bar');\nconsole.log(expr.test('foo\\nbar'));\n```\n\n## `br`\n\nAn alias for [`lineBreak`](#linebreak).\n\n## `tab`\n\nMatch a [tab character](//codepoints.net/U+0009).\n\n```js\nconst tabs = VerEx().tab();\nconst code = '\\tconsole.log(\"tabs vs spaces\")';\n\n// => '    console.log(\"tabs vs spaces\")'\nconsole.log(tabs.replace(code, '    '));\n```\n\n## `word`\n\nMatch a word—a string of word characters (a–z, A–Z, 0–9 or \\_).\n\n```js\nconst word = VerEx().startOfLine().word().endOfLine();\n\nconsole.log(word.test('foo')); // => true\nword.lastIndex = 0;\nconsole.log(word.test('foo-bar')); // => false\n```\n\n## `digit`\n\nMatch a digit (0–9).\n\n```js\nconst digit = VerEx().digit();\nconsole.log(digit.test('2')); // => true\n```\n\n## `whitespace`\n\nMatch a whitespace character (one of [space](//codepoints.net/U+0020), [tab](//codepoints.net/U+0009), [carriage return](//codepoints.net/U+000D), [new line](//codepoints.net/U+000), [vertical tab](//codepoints.net/U+000B) and [form feed](//codepoints.net/U+000C)).\n\n```js\nconst expr = VerEx().word().whitespace().word();\nconsole.log(expr.test('word\\tword')); // => true\n```\n"
  },
  {
    "path": "docs/VerbalExpression/utilities.md",
    "content": "# Utilities\n\n## `static sanitize`\n\nEscape characters expected special by regex engines (all of `.`, `|`, `*`, `?`, `+`, `(`, `)`, `{`, `}`, `^`, `$`, `\\`, `:`, `=`, `[` and `]`).\n\nParameter | Expected type | Description\n----------|---------------|-------------------\n`value`   | `String`      | String to sanitize\n\nThis method will not be accessible from outside the source file since `VerEx()` returns an instance of the class rather than the class itself.\n\n```js\nconst stringToEscape = '(http://example.com?arg=foo+bar)';\n\n// => '\\(http:\\/\\/example.com\\?arg\\=foo\\+bar\\)'\nconsole.log(VerbalExpression.sanitize(stringToEscape));\n```\n\n`sanitize` is a static method on the `VerbalExpression` class. However, it is also exposed as `VerEx().sanitize`.\n\n## `add`\n\nAppend a literal expression to the object.\n\nParameter                   | Expected type | Description\n----------------------------|---------------|--------------------------------\n`value` (defaults to `''`)  | `String`      | Expression to add to the object\n\n```js\nconst expr = VerEx();\nexpr.add('(foo)?(?:bar)*');\n\nconsole.log(expr); // => /(foo)?(?:bar)*/gm\n```\n"
  },
  {
    "path": "docs/_config.yml",
    "content": "title: JSVerbalExpressions Docs\ndescription: API Documentation for JSVerbalExpressions.\nrepository: VerbalExpressions/JSVerbalExpressions\n\nshow_downloads: true\n\ntheme: jekyll-theme-minimal\n\nexclude:\n    - Gemfile\n    - Gemfile.lock\n    - .gitignore\n\ncdn_url: https://jsdelivr.com/package/npm/verbal-expressions\nnpm_url: https://npmjs.com/package/verbal-expressions\nminified_url: https://cdn.jsdelivr.net/npm/verbal-expressions@latest/dist/verbalexpressions.min.js\n\n"
  },
  {
    "path": "docs/_layouts/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ site.lang | default: \"en-US\" }}\">\n    <head>\n        <meta charset=\"UTF-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n        {% seo %}\n\n        <link rel=\"stylesheet\" href=\"{{ \"/assets/css/style.css\" | relative_url }}\">\n\n        <!--[if lt IE 9]>\n            <script src=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js\"></script>\n        <![endif]-->\n    </head>\n    <body>\n        <div class=\"wrapper\">\n            <header>\n                <h1><a href=\"{{ \"/\" | absolute_url }}\">{{ site.title | default: site.github.repository_name }}</a></h1>\n\n                <p>{{ site.description | default: site.github.project_tagline }}</p>\n\n                {% if site.logo %}\n                    <img src=\"{{ site.logo | relative_url }}\" alt=\"Logo\" />\n                {% endif %}\n\n                {% if site.github.is_project_page %}\n                <p class=\"view\"><a href=\"{{ site.github.repository_url }}\">View the Project on GitHub <br> <small>{{ site.github.repository_nwo }}</small></a></p>\n                {% endif %}\n\n                {% if site.github.is_user_page %}\n                <p class=\"view\"><a href=\"{{ site.github.owner_url }}\">View My GitHub Profile</a></p>\n                {% endif %}\n\n                <br>\n\n                <a href=\"{{ \"/VerEx\" | absolute_url }}\"><code>VerEx</code></a> • <a href=\"{{ \"/VerbalExpression\" | absolute_url }}\"><code>VerbalExpression</code></a>\n\n                <br> <br> <br>\n\n                <ul>\n                    <li><a href=\"{{ site.minified_url }}\">Download <strong>Minified</strong></a></li>\n                    <li><a href=\"{{ site.cdn_url }}\">Use via <strong>JSDelivr</strong></a></li>\n                    <li><a href=\"{{ site.npm_url }}\">View on <strong>NPM</strong></a></li>\n                </ul>\n            </header>\n\n            <section> {{ content }} </section>\n        </div>\n        <script src=\"{{ \"/assets/js/scale.fix.js\" | relative_url }}\"></script>\n    </body>\n</html>\n"
  },
  {
    "path": "docs/assets/css/style.scss",
    "content": "---\n---\n\n@import \"{{ site.theme }}\";\n\n.wrapper {\n    width: 900px;\n}\n\nsection {\n    width: 540px;\n}\n\nul {\n    margin-bottom: 5px;\n    list-style: none;\n    padding-left: 2em;\n}\n\nhr {\n    margin: 20px 0;\n}\n\na:hover {\n    font-weight: inherit;\n}\n\na code {\n    color: #267CB9;\n}\n\na code:hover {\n    color: #006699;\n}\n\ndetails {\n    padding-bottom: 20px;\n}\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\ntitle: Home\n---\n\nVerbalExpressions is a JavaScript library that helps to construct difficult regular expressions. For more details, refer to the [README](//github.com/VerbalExpressions/JSVerbalExpressions#readme).\n\n# Table Of Contents\n\n- [`VerEx`](VerEx)\n- [`VerbalExpression`](VerbalExpression)\n    - [Constructor](VerbalExpression/constructor)\n    - [Utilities](VerbalExpression/utilities)\n    - [Rules](VerbalExpression/rules)\n    - [Special Characters](VerbalExpression/special-characters)\n    - [Modifiers](VerbalExpression/modifiers)\n    - [Loops](VerbalExpression/loops)\n    - [Capture Groups](VerbalExpression/capture-groups)\n    - [Miscellaneous](VerbalExpression/miscellaneous)\n\n___\n\nMethods have a return type of [`VerbalExpression`](VerbalExpressions) except where mentioned otherwise. If there is no mention of a method's parameters, it is to be assumed that it has none.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"verbal-expressions\",\n  \"description\": \"JavaScript Regular expressions made easy\",\n  \"version\": \"1.0.2\",\n  \"keywords\": [\n    \"regular expressions\",\n    \"regex\"\n  ],\n  \"homepage\": \"https://github.com/VerbalExpressions/JSVerbalExpressions\",\n  \"devDependencies\": {\n    \"@babel/preset-env\": \"^7.12.1\",\n    \"ava\": \"^3.13.0\",\n    \"babel-core\": \"^6.26.3\",\n    \"babel-plugin-transform-builtin-extend\": \"^1.1.2\",\n    \"eslint\": \"^8.10.0\",\n    \"eslint-config-airbnb\": \"^19.0.4\",\n    \"eslint-plugin-import\": \"^2.22.1\",\n    \"eslint-plugin-jsx-a11y\": \"^6.4.1\",\n    \"eslint-plugin-react\": \"^7.21.5\",\n    \"grunt\": \"^1.3.0\",\n    \"grunt-ava\": \"^0.19.0\",\n    \"grunt-babel\": \"^8.0.0\",\n    \"grunt-contrib-uglify\": \"^5.0.0\",\n    \"grunt-eslint\": \"^24.0.0\",\n    \"grunt-markdownlint\": \"^3.1.0\",\n    \"grunt-sourcemap-localize\": \"^0.1.0\",\n    \"grunt-umd\": \"^3.0.0\",\n    \"nyc\": \"^15.1.0\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/VerbalExpressions/JSVerbalExpressions.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/VerbalExpressions/JSVerbalExpressions/issues\"\n  },\n  \"main\": \"dist/verbalexpressions.js\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"test\": \"grunt test\",\n    \"test:verbose\": \"grunt test:verbose\",\n    \"compile\": \"grunt compile\",\n    \"grunt\": \"grunt\",\n    \"build\": \"grunt build\"\n  },\n  \"types\": \"./typings/VerbalExpressions.d.ts\",\n  \"engines\": {\n    \"node\": \">=9.2.0\"\n  },\n  \"dependencies\": {},\n  \"prettier\": {\n    \"singleQuote\": true\n  }\n}\n"
  },
  {
    "path": "test/tests.js",
    "content": "const test = require('ava');\nconst VerEx = require('../dist/verbalexpressions');\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#Using_test()_on_a_regex_with_the_global_flag\nfunction resetLastIndex(regex) {\n    regex.lastIndex = 0;\n}\n\ntest('constructor', (t) => {\n    const testRegex = VerEx();\n\n    t.true(testRegex instanceof RegExp, 'Should extend RegExp');\n    t.is(testRegex.toString(), '/(?:)/gm', 'Should be empty regex with global, multiline matching');\n});\n\n// Utility //\n\ntest('sanitize', (t) => {\n    const testString = '$a^b\\\\c|d(e)f[g]h{i}j.k*l+m?n:o=p';\n    const escaped = '\\\\$a\\\\^b\\\\\\\\c\\\\|d\\\\(e\\\\)f\\\\[g\\\\]h\\\\{i\\\\}j\\\\.k\\\\*l\\\\+m\\\\?n\\\\:o\\\\=p';\n\n    t.is(VerEx().sanitize(testString), escaped, 'Special characters should be sanitized');\n\n    t.is(VerEx().sanitize(42), 42);\n    t.is(VerEx().sanitize(/foo/), 'foo');\n\n    t.notThrows(() => VerEx().sanitize());\n    t.notThrows(() => VerEx().sanitize(NaN));\n    t.notThrows(() => VerEx().sanitize(null));\n    t.notThrows(() => VerEx().sanitize(true));\n});\n\ntest('add', (t) => {\n    let testRegex = VerEx().startOfLine().withAnyCase().endOfLine();\n    testRegex = testRegex.add('(?:foo)?');\n\n    t.true(testRegex.source.startsWith('^'), 'Should retain old prefixes');\n    t.true(testRegex.source.endsWith('$'), 'Should retain old suffixes');\n\n    t.true(testRegex.test('foo'), 'Should add new rules');\n    resetLastIndex(testRegex);\n    t.true(testRegex.test(''), 'Should add new rules');\n\n    t.true(testRegex.flags.includes('i'), 'Should retain old modifiers');\n});\n\n// Rules //\n\ntest('startOfLine', (t) => {\n    let testRegex = VerEx().startOfLine().then('a');\n    let testString = 'a';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'ba';\n    t.false(testRegex.test(testString));\n\n    testRegex = testRegex.startOfLine(false); // start of line is no longer necessary\n    testString = 'ba';\n    t.true(testRegex.test(testString));\n});\n\ntest('endOfLine', (t) => {\n    let testRegex = VerEx().find('a').endOfLine();\n    let testString = 'a';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'ab';\n    t.false(testRegex.test(testString));\n\n    testRegex = testRegex.endOfLine(false); // end of line is no longer necessary\n    testString = 'ab';\n    t.true(testRegex.test(testString));\n});\n\nfunction then(name, t) {\n    let testRegex = VerEx()[name]('a');\n    let testString = 'a';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'b';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = '';\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx()[name]('a')[name]('b');\n    testString = 'ab';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'ac';\n    t.false(testRegex.test(testString));\n}\n\ntest('then', (t) => {\n    then('then', t);\n});\n\ntest('find', (t) => {\n    then('find', t);\n});\n\ntest('maybe', (t) => {\n    const testRegex = VerEx().startOfLine().then('a').maybe('b');\n    let testString = 'acb';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'abc';\n    t.true(testRegex.test(testString));\n});\n\ntest('or', (t) => {\n    let testRegex = VerEx().startOfLine().then('abc').or('def');\n    let testString = 'defzzz';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'abczzz';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'xyzabc';\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().then('abc').or().then('def');\n    testString = 'defzzz';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'abczzz';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'xyzabc';\n    t.false(testRegex.test(testString));\n});\n\ntest('anything', (t) => {\n    const testRegex = VerEx().startOfLine().anything();\n    let testString = 'foo';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = '';\n    t.true(testRegex.test(testString), 'Should be able to match zero characters');\n});\n\ntest('anythingBut', (t) => {\n    let testRegex = VerEx().startOfLine().anythingBut('br').endOfLine();\n    let testString = 'foobar';\n\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foo_a_';\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().anythingBut('br');\n    testString = 'bar';\n    t.true(testRegex.test(testString), 'Should be able to match zero characters');\n\n    testRegex = VerEx().startOfLine().anythingBut(['b', 'r']).endOfLine();\n    testString = 'foobar';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foo_a_';\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().anythingBut(['b', 'r']);\n    testString = 'bar';\n    t.true(testRegex.test(testString), 'Should be able to match zero characters');\n});\n\ntest('something', (t) => {\n    const testRegex = VerEx().something();\n    let testString = '';\n\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'a';\n    t.true(testRegex.test(testString));\n});\n\ntest('somethingBut', (t) => {\n    let testRegex = VerEx().startOfLine().somethingBut('abc').endOfLine();\n    let testString = '';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foo';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'fab';\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().somethingBut(['a', 'b', 'c']).endOfLine();\n    testString = '';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foo';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'fab';\n    t.false(testRegex.test(testString));\n});\n\nfunction anyOf(name, t) {\n    let testRegex = VerEx().startOfLine().then('a')[name]('xyz');\n    let testString = 'ay';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'ab';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'a';\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().then('a')[name](['x', 'y', 'z']);\n    testString = 'ay';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'ab';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'a';\n    t.false(testRegex.test(testString));\n}\n\ntest('anyOf', (t) => {\n    anyOf('anyOf', t);\n});\n\ntest('any', (t) => {\n    anyOf('any', t);\n});\n\ntest('not', (t) => {\n    const testRegex = VerEx().startOfLine().not('foo').anything().endOfLine();\n    let testString = 'foobar';\n\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'bar';\n    t.true(testRegex.test(testString));\n});\n\ntest('range', (t) => {\n    let testRegex = VerEx().startOfLine().range('a', 'z', '0', '9').oneOrMore().endOfLine();\n    let testString = 'foobarbaz123';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'fooBarBaz_123';\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().range('a', 'z', '0').oneOrMore().endOfLine();\n    testString = 'foobarbaz';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foobarbaz123';\n    t.false(testRegex.test(testString), 'Should ignore extra parameters');\n});\n\n// Special characters //\n\nfunction lineBreak(name, t) {\n    const testRegex = VerEx().startOfLine().then('abc')[name]().then('def');\n    let testString = 'abc\\r\\ndef';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'abc\\ndef';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'abc\\rdef';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'abc\\r\\n\\ndef';\n    t.false(testRegex.test(testString));\n}\n\ntest('lineBreak', (t) => {\n    lineBreak('lineBreak', t);\n});\n\ntest('br', (t) => {\n    lineBreak('br', t);\n});\n\ntest('tab', (t) => {\n    const testRegex = VerEx().startOfLine().tab().then('abc');\n    let testString = '\\tabc';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'abc';\n    t.false(testRegex.test(testString));\n});\n\ntest('word', (t) => {\n    let testRegex = VerEx().startOfLine().word().endOfLine();\n    let testString = 'azertyuiopqsdfghjklmwxcvbn0123456789_';\n\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().word();\n    testString = '. @[]|,&~-';\n    t.false(testRegex.test(testString));\n});\n\ntest('digit', (t) => {\n    let testRegex = VerEx().startOfLine().digit().oneOrMore().endOfLine();\n    let testString = '0123456789';\n\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().digit();\n    testString = '-.azertyuiopqsdfghjklmwxcvbn @[]|,_&~';\n    t.false(testRegex.test(testString));\n});\n\ntest('whitespace', (t) => {\n    const testRegex = VerEx().startOfLine().whitespace().oneOrMore().searchOneLine().endOfLine();\n    let testString = ' \\t\\r\\n\\v\\f';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'a z';\n    t.false(testRegex.test(testString));\n});\n\n// Modifiers //\n\ntest('addModifier', (t) => {\n    let testRegex = VerEx().addModifier('y');\n    t.true(testRegex.flags.includes('y'));\n\n    t.notThrows(() => {\n        testRegex = VerEx().addModifier('g');\n    }, 'Should not add extra modifier if it already exists');\n});\n\ntest('removeModifier', (t) => {\n    const testRegex = VerEx().removeModifier('g');\n    t.false(testRegex.flags.includes('g'));\n});\n\ntest('withAnyCase', (t) => {\n    let testRegex = VerEx().startOfLine().then('a');\n    let testString = 'A';\n\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().then('a').withAnyCase();\n    testString = 'A';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'a';\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().then('a').withAnyCase(false);\n    testString = 'A';\n    t.false(testRegex.test(testString));\n});\n\ntest('stopAtFirst', (t) => {\n    let testRegex = VerEx().find('foo');\n    const testString = 'foofoofoo';\n\n    t.is(testString.match(testRegex).length, 3, 'Should match all \"foo\"s');\n\n    testRegex = VerEx().find('foo').stopAtFirst();\n    t.is(testString.match(testRegex).length, 1, 'Should match one \"foo\"');\n\n    testRegex = VerEx().find('foo').stopAtFirst(false);\n    t.is(testString.match(testRegex).length, 3, 'Should match all \"foo\"s');\n});\n\ntest('searchOneLine', (t) => {\n    let testRegex = VerEx().startOfLine().then('b').endOfLine();\n    const testString = 'a\\nb\\nc';\n\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine();\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine(false);\n    t.true(testRegex.test(testString));\n});\n\n// Loops //\n\ntest('repeatPrevious', (t) => {\n    let testRegex = VerEx().startOfLine().find('foo').repeatPrevious(3).endOfLine();\n    let testString = 'foofoofoo';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foofoo';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foofoofoofoo';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'bar';\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().find('foo').repeatPrevious(1, 3).endOfLine();\n\n    for (let i = 0; i <= 4; i++) {\n        resetLastIndex(testRegex);\n        testString = 'foo'.repeat(i);\n\n        if (i < 1 || i > 3) {\n            t.false(testRegex.test(testString));\n        } else {\n            t.true(testRegex.test(testString));\n        }\n    }\n\n    testRegex = VerEx().startOfLine().find('foo').repeatPrevious().endOfLine();\n    testString = 'foofoo';\n    t.false(testRegex.test(testString), 'Should silently fail on edge cases');\n\n    testRegex = VerEx().startOfLine().find('foo').repeatPrevious(1, 2, 3).endOfLine();\n    testString = 'foofoo';\n    t.false(testRegex.test(testString), 'Should silently fail on edge cases');\n});\n\ntest('oneOrMore', (t) => {\n    const testRegex = VerEx().startOfLine().then('foo').oneOrMore().endOfLine();\n    let testString = 'foo';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foofoo';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'bar';\n    t.false(testRegex.test(testString));\n});\n\ntest('multiple', (t) => {\n    let testRegex = VerEx().startOfLine().find(' ').multiple().endOfLine();\n    let testString = '   ';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = ' a ';\n    t.false(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().multiple('foo').endOfLine();\n    testString = 'foo';\n\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foofoofoo';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = '';\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().multiple('foo', 2).endOfLine();\n    testString = 'foo';\n    t.false(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foofoo';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    testString = 'foofoofoo';\n    t.true(testRegex.test(testString));\n\n    testRegex = VerEx().startOfLine().multiple('foo', 2, 5).endOfLine();\n\n    for (let i = 0; i <= 6; i++) {\n        resetLastIndex(testRegex);\n        testString = 'foo'.repeat(i);\n\n        if (i < 2 || i > 5) {\n            t.false(testRegex.test(testString));\n        } else {\n            t.true(testRegex.test(testString));\n        }\n    }\n});\n\n// Capture groups //\n\ntest('capture groups', (t) => {\n    let testRegex = VerEx().find('foo').beginCapture().then('bar');\n    let testString = 'foobar';\n\n    t.true(testRegex.test(testString), 'Expressions with incomplete capture groups should work');\n\n    testRegex = testRegex.endCapture().then('baz');\n    testString = 'foobarbaz';\n    t.true(testRegex.test(testString));\n\n    resetLastIndex(testRegex);\n    const matches = testRegex.exec(testString);\n    t.is(matches[1], 'bar');\n});\n\n// Miscellaneous //\n\ntest('replace', (t) => {\n    const testRegex = VerEx().find(' ');\n    const testString = 'foo bar baz';\n\n    t.is(testRegex.replace(testString, '_'), 'foo_bar_baz');\n});\n\ntest('toRegExp', (t) => {\n    const testRegex = VerEx().anything();\n    const converted = testRegex.toRegExp();\n\n    t.is(converted.toString(), testRegex.toString(), 'Converted regex should have same behaviour');\n});\n"
  },
  {
    "path": "typings/VerbalExpressions.d.ts",
    "content": "// Type definitions for JSVerbalExpressions\n// Project: https://github.com/VerbalExpressions/JSVerbalExpressions\n// Definitions by: Mihai Ionut Vilcu <https://github.com/ionutvmi>\n// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped\n\ntype RegExpFlags = \"g\" | \"i\" | \"m\" | \"u\" | \"y\";\ntype Appendable = VerbalExpression | RegExp | string | number;\n\ninterface VerbalExpression extends RegExp {\n    // Utility //\n    /** Sanitation function for adding anything safely to the expression */\n    sanitize(value: Appendable): VerbalExpression;\n    /** Append literal expression to the object. Also refreshes the expression. */\n    add(value: string | number): VerbalExpression;\n\n    // Rules //\n    /** Mark the expression to end at the last character of the line. */\n    startOfLine(enable?: boolean): VerbalExpression;\n    /** Mark the expression to start at the beginning of the line. */\n    endOfLine(enable?: boolean): VerbalExpression;\n    /** Add a string to the expression */\n    then(value: Appendable): VerbalExpression;\n    /** Add a string to the expression. Alias for then() */\n    find(value: Appendable): VerbalExpression;\n    /** Add a string to the expression that might appear once (or not). */\n    maybe(value: Appendable): VerbalExpression;\n    /** Add a alternative expression to be matched. */\n    or(value?: Appendable): VerbalExpression;\n    /** Match any character(s) any (including zero) number of times. */\n    anything(): VerbalExpression;\n    anythingBut(value: Appendable | string[]): VerbalExpression;\n    /** Match any character(s) at least once. */\n    something(): VerbalExpression;\n    somethingBut(value: Appendable | string[]): VerbalExpression;\n    /** Match any of the provided values */\n    anyOf(value: Appendable | string[]): VerbalExpression;\n    /** Match any of the provided values. Alias for anyOf() */\n    any(value: Appendable | string[]): VerbalExpression;\n    /** Ensure that the parameter does not follow. */\n    not(value: Appendable): VerbalExpression;\n    /** Add expression to match a range (or multiply ranges) */\n    range(...values: string[]): VerbalExpression;\n\n    // Special Characters\n    /** Add universal line break expression */\n    lineBreak(): VerbalExpression;\n    /** Add universal line break expression. Alias for lineBreak() */\n    br(): VerbalExpression;\n    /** Add expression to match a tab character */\n    tab(): VerbalExpression;\n    /** Add expression to match a word */\n    word(): VerbalExpression;\n    /** Add expression to match a digit */\n    digit(): VerbalExpression;\n    /** Add expression to match a whitespace character */\n    whitespace(): VerbalExpression;\n\n    // Modifiers //\n    /** Adds a modifier to the expression. */\n    addModifier(modifier: RegExpFlags): VerbalExpression;\n    /** Removes a modifier to the expression. */\n    removeModifier(modifier: RegExpFlags): VerbalExpression;\n    /** Makes the expression case insensitive */\n    withAnyCase(enable?: boolean): VerbalExpression;\n    /** Removes the 'g' modifier. */\n    stopAtFirst(enable?: boolean): VerbalExpression;\n    /** Removes the 'm' modifier. */\n    searchOneLine(enable?: boolean): VerbalExpression;\n\n    // Loops //\n    /** Repeat the previous item between mix and max (inclusive) times. */\n    repeatPrevious(min: number, max: number): VerbalExpression;\n    /** Repeat the previous item exactly count times. */\n    repeatPrevious(count: number): VerbalExpression;\n    /** Match the previous stuff one or more times. */\n    oneOrMore(): VerbalExpression;\n    /** Match something greater than or equal to min number of times. Or of upper is set. Match something between min and max (inclusive) number of times. */\n    multiple(value: string, lower: number, upper?: number): VerbalExpression;\n    /** Match something zero or more times. */\n    multiple(value: string): VerbalExpression;\n    /** Match the previous group any number of times. */\n    multiple(): VerbalExpression;\n    /** Starts a capturing group */\n    beginCapture(): VerbalExpression;\n    /** Emds a capturing group */\n    endCapture(): VerbalExpression;\n\n    // Miscellaneous\n    replace(source: string, value: string): string;\n    /** Converts the verbal expression to a RegExp object */\n    toRegExp(): RegExp;\n}\n\ninterface VerbalExpressionConstructor {\n    new(): VerbalExpression;\n    (): VerbalExpression;\n    prototype: VerbalExpression;\n}\n\ndeclare var VerEx: VerbalExpressionConstructor;\nexport = VerEx;\n"
  }
]