~ancarda/gemtext-parser

3534d736a456b4c49be125df4cf55f1925387ebf — Mark Dain 1 year, 10 months ago
Initial commit
A  => .gitattributes +8 -0
@@ 1,8 @@
/.gitattributes  export-ignore
/CONTRIBUTING.md export-ignore
/README.md       export-ignore
/phpcs.xml       export-ignore
/phpstan.neon    export-ignore
/phpunit.xml     export-ignore
/tests           export-ignore
/infection.json  export-ignore

A  => LICENSE +21 -0
@@ 1,21 @@
MIT License

Copyright (c) 2022 Mark Dain <mark@markdain.net>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

A  => README.md +75 -0
@@ 1,75 @@
# ancarda/gemtext-parser

_Gemtext (text/gemini) parser and HTML encoder_

This package implements a PHP parser for Gemtext (`text/gemini`) as specified
here: https://gemini.circumlunar.space/docs/gemtext.gmi

## Useful Links

* Source Code:   <https://git.sr.ht/~ancarda/gemtext-parser/>
* Issue Tracker: <https://todo.sr.ht/~ancarda/gemtext-parser/>
* Mailing List:  <https://lists.sr.ht/~ancarda/gemtext-parser/>

## Usage

All the low level classes are built around `Generator`, which makes plugging in
middleware easy while keeping memory usage low.

Unfortunately, Generators can be a bit of work to actually use. As such, a 
utility class, `SimpleTransformer` is available which abstracts this away if
you just want a Gemtext to HTML conversion quickly and easily.

Here's how to convert Gemtext to HTML with the low level (`Generator`) API:

```php
<?php

$parser  = new Ancarda\Gemini\Gemtext\Parser;
$encoder = new Ancarda\Gemini\Gemtext\Encoder\HTML;

$nodes = $parser->parse(explode("\n", $gemtext));

$html = implode("\n", iterator_to_array($encoder->encode($nodes)));
```

And here's the higher level utility class, which abstracts this away:

```php
<?php

$transformer = new \Ancarda\Gemini\Gemtext\Util\SimpleTransformer;

echo $transformer->transform($gemText);
```

### Pipelining

You can create lightweight middleware by creating a function that accepts and
returns `Generator<Node>`. This function would be inserted between `encode` and
`parse`, like so:

```
$encoder->encode($middleware($parser->parse(explode("\n", $gemtext))));
```

Here, middleware's `__invoke` method accepts and returns `Generator<Node>`.
Middleware could make modifications, inject new nodes, drop some nodes, and so
on. For instance:

```php
<?php

$reverse_paragraphs = new class {
    public function __invoke(Generator $nodes): Generator
    {
        foreach ($nodes as $node) {
            if ($node instanceof Paragraph) {
                yield new Paragraph(strrev($node->getText()));
            } else {
                yield $node;
            }
        }
    }
};
```

A  => composer.json +52 -0
@@ 1,52 @@
{
    "name": "ancarda/gemtext",
    "description": "Gemtext (text/gemini) parser with conversion to HTML",
    "type": "library",
    "license": "MIT",
    "config": {
        "allow-plugins": {
            "infection/extension-installer": true
        },
        "sort-packages": true,
        "platform": {
            "php": "8.0"
        }
    },
    "autoload": {
        "psr-4": {
            "Ancarda\\Gemini\\Gemtext\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Test\\": "tests/"
        }
    },
    "require": {
        "php": "^8.0"
    },
    "require-dev": {
        "ancarda/coverage-enforcer": "^1.0",
        "infection/infection": "^0.26.6",
        "phpstan/phpstan": "^1.5",
        "phpstan/phpstan-phpunit": "^1.1",
        "phpstan/phpstan-strict-rules": "^1.1",
        "phpunit/phpunit": "^9.5",
        "squizlabs/php_codesniffer": "^3.6"
    },
    "scripts": {
        "check-everything": [
            "@analyze",
            "@check-style",
            "@test",
            "@check-tests",
            "@check-coverage"
        ],
        "analyze": "phpstan",
        "check-coverage": "enforce-coverage --minStmtCov 100 var/coverage/coverage.clover.xml",
        "check-style": "phpcs",
        "check-tests": "infection --min-msi=100",
        "fix-style": "phpcbf",
        "test": "phpunit"
    }
}

A  => composer.lock +4384 -0
@@ 1,4384 @@
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
        "This file is @generated automatically"
    ],
    "content-hash": "756f337dd3dbfdea4a86a91e293eae6d",
    "packages": [],
    "packages-dev": [
        {
            "name": "ancarda/coverage-enforcer",
            "version": "1.0.1",
            "source": {
                "type": "git",
                "url": "https://github.com/ancarda/coverage-enforcer.git",
                "reference": "380feec425b57e732c52e7e10f1b779751a00983"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/ancarda/coverage-enforcer/zipball/380feec425b57e732c52e7e10f1b779751a00983",
                "reference": "380feec425b57e732c52e7e10f1b779751a00983",
                "shasum": ""
            },
            "require": {
                "ext-simplexml": "*",
                "php": "^7.3|^8.0",
                "symfony/console": "^5.1|^6.0"
            },
            "require-dev": {
                "composer/package-versions-deprecated": "1.11.99.1",
                "infection/infection": "^0.18.2",
                "phpstan/phpstan": "^0.12.82",
                "phpstan/phpstan-phpunit": "^0.12.18",
                "phpstan/phpstan-strict-rules": "^0.12.9",
                "phpunit/phpunit": "^9.5",
                "squizlabs/php_codesniffer": "^3.5"
            },
            "bin": [
                "bin/enforce-coverage"
            ],
            "type": "project",
            "autoload": {
                "psr-4": {
                    "Ancarda\\CodeCoverage\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Enforces a minimum Code Coverage using a Coverage Clover XML file",
            "support": {
                "source": "https://github.com/ancarda/coverage-enforcer/tree/1.0.1"
            },
            "time": "2022-02-25T22:15:18+00:00"
        },
        {
            "name": "composer/pcre",
            "version": "3.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/pcre.git",
                "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd",
                "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd",
                "shasum": ""
            },
            "require": {
                "php": "^7.4 || ^8.0"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.3",
                "phpstan/phpstan-strict-rules": "^1.1",
                "symfony/phpunit-bridge": "^5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "3.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Composer\\Pcre\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                }
            ],
            "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
            "keywords": [
                "PCRE",
                "preg",
                "regex",
                "regular expression"
            ],
            "support": {
                "issues": "https://github.com/composer/pcre/issues",
                "source": "https://github.com/composer/pcre/tree/3.0.0"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
                    "type": "tidelift"
                }
            ],
            "time": "2022-02-25T20:21:48+00:00"
        },
        {
            "name": "composer/xdebug-handler",
            "version": "3.0.3",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/xdebug-handler.git",
                "reference": "ced299686f41dce890debac69273b47ffe98a40c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
                "reference": "ced299686f41dce890debac69273b47ffe98a40c",
                "shasum": ""
            },
            "require": {
                "composer/pcre": "^1 || ^2 || ^3",
                "php": "^7.2.5 || ^8.0",
                "psr/log": "^1 || ^2 || ^3"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.0",
                "phpstan/phpstan-strict-rules": "^1.1",
                "symfony/phpunit-bridge": "^6.0"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Composer\\XdebugHandler\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "John Stevenson",
                    "email": "john-stevenson@blueyonder.co.uk"
                }
            ],
            "description": "Restarts a process without Xdebug.",
            "keywords": [
                "Xdebug",
                "performance"
            ],
            "support": {
                "irc": "irc://irc.freenode.org/composer",
                "issues": "https://github.com/composer/xdebug-handler/issues",
                "source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
            },
            "funding": [
                {
                    "url": "https://packagist.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/composer",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/composer/composer",
                    "type": "tidelift"
                }
            ],
            "time": "2022-02-25T21:32:43+00:00"
        },
        {
            "name": "doctrine/instantiator",
            "version": "1.4.1",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/instantiator.git",
                "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
                "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
                "shasum": ""
            },
            "require": {
                "php": "^7.1 || ^8.0"
            },
            "require-dev": {
                "doctrine/coding-standard": "^9",
                "ext-pdo": "*",
                "ext-phar": "*",
                "phpbench/phpbench": "^0.16 || ^1",
                "phpstan/phpstan": "^1.4",
                "phpstan/phpstan-phpunit": "^1",
                "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
                "vimeo/psalm": "^4.22"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Marco Pivetta",
                    "email": "ocramius@gmail.com",
                    "homepage": "https://ocramius.github.io/"
                }
            ],
            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
            "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
            "keywords": [
                "constructor",
                "instantiate"
            ],
            "support": {
                "issues": "https://github.com/doctrine/instantiator/issues",
                "source": "https://github.com/doctrine/instantiator/tree/1.4.1"
            },
            "funding": [
                {
                    "url": "https://www.doctrine-project.org/sponsorship.html",
                    "type": "custom"
                },
                {
                    "url": "https://www.patreon.com/phpdoctrine",
                    "type": "patreon"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
                    "type": "tidelift"
                }
            ],
            "time": "2022-03-03T08:28:38+00:00"
        },
        {
            "name": "infection/abstract-testframework-adapter",
            "version": "0.5.0",
            "source": {
                "type": "git",
                "url": "https://github.com/infection/abstract-testframework-adapter.git",
                "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/infection/abstract-testframework-adapter/zipball/18925e20d15d1a5995bb85c9dc09e8751e1e069b",
                "reference": "18925e20d15d1a5995bb85c9dc09e8751e1e069b",
                "shasum": ""
            },
            "require": {
                "php": "^7.4 || ^8.0"
            },
            "require-dev": {
                "ergebnis/composer-normalize": "^2.8",
                "friendsofphp/php-cs-fixer": "^2.17",
                "phpunit/phpunit": "^9.5"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Infection\\AbstractTestFramework\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Maks Rafalko",
                    "email": "maks.rafalko@gmail.com"
                }
            ],
            "description": "Abstract Test Framework Adapter for Infection",
            "support": {
                "issues": "https://github.com/infection/abstract-testframework-adapter/issues",
                "source": "https://github.com/infection/abstract-testframework-adapter/tree/0.5.0"
            },
            "funding": [
                {
                    "url": "https://github.com/infection",
                    "type": "github"
                },
                {
                    "url": "https://opencollective.com/infection",
                    "type": "open_collective"
                }
            ],
            "time": "2021-08-17T18:49:12+00:00"
        },
        {
            "name": "infection/extension-installer",
            "version": "0.1.2",
            "source": {
                "type": "git",
                "url": "https://github.com/infection/extension-installer.git",
                "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/infection/extension-installer/zipball/9b351d2910b9a23ab4815542e93d541e0ca0cdcf",
                "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf",
                "shasum": ""
            },
            "require": {
                "composer-plugin-api": "^1.1 || ^2.0"
            },
            "require-dev": {
                "composer/composer": "^1.9 || ^2.0",
                "friendsofphp/php-cs-fixer": "^2.18, <2.19",
                "infection/infection": "^0.15.2",
                "php-coveralls/php-coveralls": "^2.4",
                "phpstan/extension-installer": "^1.0",
                "phpstan/phpstan": "^0.12.10",
                "phpstan/phpstan-phpunit": "^0.12.6",
                "phpstan/phpstan-strict-rules": "^0.12.2",
                "phpstan/phpstan-webmozart-assert": "^0.12.2",
                "phpunit/phpunit": "^9.5",
                "vimeo/psalm": "^4.8"
            },
            "type": "composer-plugin",
            "extra": {
                "class": "Infection\\ExtensionInstaller\\Plugin"
            },
            "autoload": {
                "psr-4": {
                    "Infection\\ExtensionInstaller\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Maks Rafalko",
                    "email": "maks.rafalko@gmail.com"
                }
            ],
            "description": "Infection Extension Installer",
            "support": {
                "issues": "https://github.com/infection/extension-installer/issues",
                "source": "https://github.com/infection/extension-installer/tree/0.1.2"
            },
            "funding": [
                {
                    "url": "https://github.com/infection",
                    "type": "github"
                },
                {
                    "url": "https://opencollective.com/infection",
                    "type": "open_collective"
                }
            ],
            "time": "2021-10-20T22:08:34+00:00"
        },
        {
            "name": "infection/include-interceptor",
            "version": "0.2.5",
            "source": {
                "type": "git",
                "url": "https://github.com/infection/include-interceptor.git",
                "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/infection/include-interceptor/zipball/0cc76d95a79d9832d74e74492b0a30139904bdf7",
                "reference": "0cc76d95a79d9832d74e74492b0a30139904bdf7",
                "shasum": ""
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "^2.16",
                "infection/infection": "^0.15.0",
                "phan/phan": "^2.4 || ^3",
                "php-coveralls/php-coveralls": "^2.2",
                "phpstan/phpstan": "^0.12.8",
                "phpunit/phpunit": "^8.5",
                "vimeo/psalm": "^3.8"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Infection\\StreamWrapper\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Maks Rafalko",
                    "email": "maks.rafalko@gmail.com"
                }
            ],
            "description": "Stream Wrapper: Include Interceptor. Allows to replace included (autoloaded) file with another one.",
            "support": {
                "issues": "https://github.com/infection/include-interceptor/issues",
                "source": "https://github.com/infection/include-interceptor/tree/0.2.5"
            },
            "funding": [
                {
                    "url": "https://github.com/infection",
                    "type": "github"
                },
                {
                    "url": "https://opencollective.com/infection",
                    "type": "open_collective"
                }
            ],
            "time": "2021-08-09T10:03:57+00:00"
        },
        {
            "name": "infection/infection",
            "version": "0.26.6",
            "source": {
                "type": "git",
                "url": "https://github.com/infection/infection.git",
                "reference": "de9b6b92f00ff1cb39decddf95797a4ebec3a1ee"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/infection/infection/zipball/de9b6b92f00ff1cb39decddf95797a4ebec3a1ee",
                "reference": "de9b6b92f00ff1cb39decddf95797a4ebec3a1ee",
                "shasum": ""
            },
            "require": {
                "composer-runtime-api": "^2.0",
                "composer/xdebug-handler": "^2.0 || ^3.0",
                "ext-dom": "*",
                "ext-json": "*",
                "ext-libxml": "*",
                "infection/abstract-testframework-adapter": "^0.5.0",
                "infection/extension-installer": "^0.1.0",
                "infection/include-interceptor": "^0.2.5",
                "justinrainbow/json-schema": "^5.2.10",
                "nikic/php-parser": "^4.13.2",
                "ondram/ci-detector": "^4.1.0",
                "php": "^7.4.7 || ^8.0",
                "sanmai/later": "^0.1.1",
                "sanmai/pipeline": "^5.1 || ^6",
                "sebastian/diff": "^3.0.2 || ^4.0",
                "seld/jsonlint": "^1.7",
                "symfony/console": "^3.4.29 || ^4.1.19 || ^5.0 || ^6.0",
                "symfony/filesystem": "^3.4.29 || ^4.1.19 || ^5.0 || ^6.0",
                "symfony/finder": "^3.4.29 || ^4.1.19 || ^5.0 || ^6.0",
                "symfony/process": "^3.4.29 || ^4.1.19 || ^5.0 || ^6.0",
                "thecodingmachine/safe": "^1.1.3",
                "webmozart/assert": "^1.3",
                "webmozart/path-util": "^2.3"
            },
            "conflict": {
                "dg/bypass-finals": "*",
                "phpunit/php-code-coverage": ">9 <9.1.4"
            },
            "require-dev": {
                "brianium/paratest": "^6.3",
                "ext-simplexml": "*",
                "helmich/phpunit-json-assert": "^3.0",
                "phpspec/prophecy-phpunit": "^2.0",
                "phpstan/extension-installer": "^1.1.0",
                "phpstan/phpstan": "^1.2.0",
                "phpstan/phpstan-phpunit": "^1.0.0",
                "phpstan/phpstan-strict-rules": "^1.1.0",
                "phpstan/phpstan-webmozart-assert": "^1.0.2",
                "phpunit/phpunit": "^9.3.11",
                "symfony/phpunit-bridge": "^4.4.18 || ^5.1.10",
                "symfony/yaml": "^5.0",
                "thecodingmachine/phpstan-safe-rule": "^1.1.0"
            },
            "bin": [
                "bin/infection"
            ],
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Infection\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Maks Rafalko",
                    "email": "maks.rafalko@gmail.com",
                    "homepage": "https://twitter.com/maks_rafalko"
                },
                {
                    "name": "Oleg Zhulnev",
                    "homepage": "https://github.com/sidz"
                },
                {
                    "name": "Gert de Pagter",
                    "homepage": "https://github.com/BackEndTea"
                },
                {
                    "name": "Théo FIDRY",
                    "email": "theo.fidry@gmail.com",
                    "homepage": "https://twitter.com/tfidry"
                },
                {
                    "name": "Alexey Kopytko",
                    "email": "alexey@kopytko.com",
                    "homepage": "https://www.alexeykopytko.com"
                },
                {
                    "name": "Andreas Möller",
                    "email": "am@localheinz.com",
                    "homepage": "https://localheinz.com"
                }
            ],
            "description": "Infection is a Mutation Testing framework for PHP. The mutation adequacy score can be used to measure the effectiveness of a test set in terms of its ability to detect faults.",
            "keywords": [
                "coverage",
                "mutant",
                "mutation framework",
                "mutation testing",
                "testing",
                "unit testing"
            ],
            "support": {
                "issues": "https://github.com/infection/infection/issues",
                "source": "https://github.com/infection/infection/tree/0.26.6"
            },
            "funding": [
                {
                    "url": "https://github.com/infection",
                    "type": "github"
                },
                {
                    "url": "https://opencollective.com/infection",
                    "type": "open_collective"
                }
            ],
            "time": "2022-03-07T11:40:30+00:00"
        },
        {
            "name": "justinrainbow/json-schema",
            "version": "5.2.12",
            "source": {
                "type": "git",
                "url": "https://github.com/justinrainbow/json-schema.git",
                "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/ad87d5a5ca981228e0e205c2bc7dfb8e24559b60",
                "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1",
                "json-schema/json-schema-test-suite": "1.2.0",
                "phpunit/phpunit": "^4.8.35"
            },
            "bin": [
                "bin/validate-json"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "5.0.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "JsonSchema\\": "src/JsonSchema/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Bruno Prieto Reis",
                    "email": "bruno.p.reis@gmail.com"
                },
                {
                    "name": "Justin Rainbow",
                    "email": "justin.rainbow@gmail.com"
                },
                {
                    "name": "Igor Wiedler",
                    "email": "igor@wiedler.ch"
                },
                {
                    "name": "Robert Schönthal",
                    "email": "seroscho@googlemail.com"
                }
            ],
            "description": "A library to validate a json schema.",
            "homepage": "https://github.com/justinrainbow/json-schema",
            "keywords": [
                "json",
                "schema"
            ],
            "support": {
                "issues": "https://github.com/justinrainbow/json-schema/issues",
                "source": "https://github.com/justinrainbow/json-schema/tree/5.2.12"
            },
            "time": "2022-04-13T08:02:27+00:00"
        },
        {
            "name": "myclabs/deep-copy",
            "version": "1.11.0",
            "source": {
                "type": "git",
                "url": "https://github.com/myclabs/DeepCopy.git",
                "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
                "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
                "shasum": ""
            },
            "require": {
                "php": "^7.1 || ^8.0"
            },
            "conflict": {
                "doctrine/collections": "<1.6.8",
                "doctrine/common": "<2.13.3 || >=3,<3.2.2"
            },
            "require-dev": {
                "doctrine/collections": "^1.6.8",
                "doctrine/common": "^2.13.3 || ^3.2.2",
                "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
            },
            "type": "library",
            "autoload": {
                "files": [
                    "src/DeepCopy/deep_copy.php"
                ],
                "psr-4": {
                    "DeepCopy\\": "src/DeepCopy/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Create deep copies (clones) of your objects",
            "keywords": [
                "clone",
                "copy",
                "duplicate",
                "object",
                "object graph"
            ],
            "support": {
                "issues": "https://github.com/myclabs/DeepCopy/issues",
                "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
            },
            "funding": [
                {
                    "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
                    "type": "tidelift"
                }
            ],
            "time": "2022-03-03T13:19:32+00:00"
        },
        {
            "name": "nikic/php-parser",
            "version": "v4.13.2",
            "source": {
                "type": "git",
                "url": "https://github.com/nikic/PHP-Parser.git",
                "reference": "210577fe3cf7badcc5814d99455df46564f3c077"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
                "reference": "210577fe3cf7badcc5814d99455df46564f3c077",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=7.0"
            },
            "require-dev": {
                "ircmaxell/php-yacc": "^0.0.7",
                "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
            },
            "bin": [
                "bin/php-parse"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.9-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "PhpParser\\": "lib/PhpParser"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Nikita Popov"
                }
            ],
            "description": "A PHP parser written in PHP",
            "keywords": [
                "parser",
                "php"
            ],
            "support": {
                "issues": "https://github.com/nikic/PHP-Parser/issues",
                "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2"
            },
            "time": "2021-11-30T19:35:32+00:00"
        },
        {
            "name": "ondram/ci-detector",
            "version": "4.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/OndraM/ci-detector.git",
                "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/OndraM/ci-detector/zipball/8a4b664e916df82ff26a44709942dfd593fa6f30",
                "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30",
                "shasum": ""
            },
            "require": {
                "php": "^7.1 || ^8.0"
            },
            "require-dev": {
                "ergebnis/composer-normalize": "^2.2",
                "lmc/coding-standard": "^1.3 || ^2.1",
                "php-parallel-lint/php-parallel-lint": "^1.2",
                "phpstan/extension-installer": "^1.0.5",
                "phpstan/phpstan": "^0.12.58",
                "phpstan/phpstan-phpunit": "^0.12.16",
                "phpunit/phpunit": "^7.1 || ^8.0 || ^9.0"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "OndraM\\CiDetector\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Ondřej Machulda",
                    "email": "ondrej.machulda@gmail.com"
                }
            ],
            "description": "Detect continuous integration environment and provide unified access to properties of current build",
            "keywords": [
                "CircleCI",
                "Codeship",
                "Wercker",
                "adapter",
                "appveyor",
                "aws",
                "aws codebuild",
                "azure",
                "azure devops",
                "azure pipelines",
                "bamboo",
                "bitbucket",
                "buddy",
                "ci-info",
                "codebuild",
                "continuous integration",
                "continuousphp",
                "devops",
                "drone",
                "github",
                "gitlab",
                "interface",
                "jenkins",
                "pipelines",
                "sourcehut",
                "teamcity",
                "travis"
            ],
            "support": {
                "issues": "https://github.com/OndraM/ci-detector/issues",
                "source": "https://github.com/OndraM/ci-detector/tree/4.1.0"
            },
            "time": "2021-04-14T09:16:52+00:00"
        },
        {
            "name": "phar-io/manifest",
            "version": "2.0.3",
            "source": {
                "type": "git",
                "url": "https://github.com/phar-io/manifest.git",
                "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
                "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-phar": "*",
                "ext-xmlwriter": "*",
                "phar-io/version": "^3.0.1",
                "php": "^7.2 || ^8.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.0.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Arne Blankerts",
                    "email": "arne@blankerts.de",
                    "role": "Developer"
                },
                {
                    "name": "Sebastian Heuer",
                    "email": "sebastian@phpeople.de",
                    "role": "Developer"
                },
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "Developer"
                }
            ],
            "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
            "support": {
                "issues": "https://github.com/phar-io/manifest/issues",
                "source": "https://github.com/phar-io/manifest/tree/2.0.3"
            },
            "time": "2021-07-20T11:28:43+00:00"
        },
        {
            "name": "phar-io/version",
            "version": "3.2.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phar-io/version.git",
                "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
                "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Arne Blankerts",
                    "email": "arne@blankerts.de",
                    "role": "Developer"
                },
                {
                    "name": "Sebastian Heuer",
                    "email": "sebastian@phpeople.de",
                    "role": "Developer"
                },
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "Developer"
                }
            ],
            "description": "Library for handling version information and constraints",
            "support": {
                "issues": "https://github.com/phar-io/version/issues",
                "source": "https://github.com/phar-io/version/tree/3.2.1"
            },
            "time": "2022-02-21T01:04:05+00:00"
        },
        {
            "name": "phpdocumentor/reflection-common",
            "version": "2.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
                "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
                "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-2.x": "2.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "phpDocumentor\\Reflection\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jaap van Otterdijk",
                    "email": "opensource@ijaap.nl"
                }
            ],
            "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "FQSEN",
                "phpDocumentor",
                "phpdoc",
                "reflection",
                "static analysis"
            ],
            "support": {
                "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
                "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
            },
            "time": "2020-06-27T09:03:43+00:00"
        },
        {
            "name": "phpdocumentor/reflection-docblock",
            "version": "5.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
                "reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
                "reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
                "shasum": ""
            },
            "require": {
                "ext-filter": "*",
                "php": "^7.2 || ^8.0",
                "phpdocumentor/reflection-common": "^2.2",
                "phpdocumentor/type-resolver": "^1.3",
                "webmozart/assert": "^1.9.1"
            },
            "require-dev": {
                "mockery/mockery": "~1.3.2",
                "psalm/phar": "^4.8"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "5.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "phpDocumentor\\Reflection\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Mike van Riel",
                    "email": "me@mikevanriel.com"
                },
                {
                    "name": "Jaap van Otterdijk",
                    "email": "account@ijaap.nl"
                }
            ],
            "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
            "support": {
                "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
                "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
            },
            "time": "2021-10-19T17:43:47+00:00"
        },
        {
            "name": "phpdocumentor/type-resolver",
            "version": "1.6.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/TypeResolver.git",
                "reference": "77a32518733312af16a44300404e945338981de3"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
                "reference": "77a32518733312af16a44300404e945338981de3",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0",
                "phpdocumentor/reflection-common": "^2.0"
            },
            "require-dev": {
                "ext-tokenizer": "*",
                "psalm/phar": "^4.8"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-1.x": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "phpDocumentor\\Reflection\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Mike van Riel",
                    "email": "me@mikevanriel.com"
                }
            ],
            "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
            "support": {
                "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
                "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
            },
            "time": "2022-03-15T21:29:03+00:00"
        },
        {
            "name": "phpspec/prophecy",
            "version": "v1.15.0",
            "source": {
                "type": "git",
                "url": "https://github.com/phpspec/prophecy.git",
                "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
                "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
                "shasum": ""
            },
            "require": {
                "doctrine/instantiator": "^1.2",
                "php": "^7.2 || ~8.0, <8.2",
                "phpdocumentor/reflection-docblock": "^5.2",
                "sebastian/comparator": "^3.0 || ^4.0",
                "sebastian/recursion-context": "^3.0 || ^4.0"
            },
            "require-dev": {
                "phpspec/phpspec": "^6.0 || ^7.0",
                "phpunit/phpunit": "^8.0 || ^9.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Prophecy\\": "src/Prophecy"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Konstantin Kudryashov",
                    "email": "ever.zet@gmail.com",
                    "homepage": "http://everzet.com"
                },
                {
                    "name": "Marcello Duarte",
                    "email": "marcello.duarte@gmail.com"
                }
            ],
            "description": "Highly opinionated mocking framework for PHP 5.3+",
            "homepage": "https://github.com/phpspec/prophecy",
            "keywords": [
                "Double",
                "Dummy",
                "fake",
                "mock",
                "spy",
                "stub"
            ],
            "support": {
                "issues": "https://github.com/phpspec/prophecy/issues",
                "source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
            },
            "time": "2021-12-08T12:19:24+00:00"
        },
        {
            "name": "phpstan/phpstan",
            "version": "1.5.6",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpstan.git",
                "reference": "799dd8c2d2c9c704bb55d2078078cb970cf0f6d1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/799dd8c2d2c9c704bb55d2078078cb970cf0f6d1",
                "reference": "799dd8c2d2c9c704bb55d2078078cb970cf0f6d1",
                "shasum": ""
            },
            "require": {
                "php": "^7.2|^8.0"
            },
            "conflict": {
                "phpstan/phpstan-shim": "*"
            },
            "bin": [
                "phpstan",
                "phpstan.phar"
            ],
            "type": "library",
            "autoload": {
                "files": [
                    "bootstrap.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "PHPStan - PHP Static Analysis Tool",
            "support": {
                "issues": "https://github.com/phpstan/phpstan/issues",
                "source": "https://github.com/phpstan/phpstan/tree/1.5.6"
            },
            "funding": [
                {
                    "url": "https://github.com/ondrejmirtes",
                    "type": "github"
                },
                {
                    "url": "https://github.com/phpstan",
                    "type": "github"
                },
                {
                    "url": "https://www.patreon.com/phpstan",
                    "type": "patreon"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
                    "type": "tidelift"
                }
            ],
            "time": "2022-04-15T11:13:37+00:00"
        },
        {
            "name": "phpstan/phpstan-phpunit",
            "version": "1.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpstan-phpunit.git",
                "reference": "09133ce914f1388a8bb8c7f8573aaa3723cff52a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/09133ce914f1388a8bb8c7f8573aaa3723cff52a",
                "reference": "09133ce914f1388a8bb8c7f8573aaa3723cff52a",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0",
                "phpstan/phpstan": "^1.5.0"
            },
            "conflict": {
                "phpunit/phpunit": "<7.0"
            },
            "require-dev": {
                "nikic/php-parser": "^4.13.0",
                "php-parallel-lint/php-parallel-lint": "^1.2",
                "phpstan/phpstan-strict-rules": "^1.0",
                "phpunit/phpunit": "^9.5"
            },
            "type": "phpstan-extension",
            "extra": {
                "phpstan": {
                    "includes": [
                        "extension.neon",
                        "rules.neon"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "PHPStan\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "PHPUnit extensions and rules for PHPStan",
            "support": {
                "issues": "https://github.com/phpstan/phpstan-phpunit/issues",
                "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.1.0"
            },
            "time": "2022-03-28T09:20:49+00:00"
        },
        {
            "name": "phpstan/phpstan-strict-rules",
            "version": "1.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpstan-strict-rules.git",
                "reference": "e12d55f74a8cca18c6e684c6450767e055ba7717"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/e12d55f74a8cca18c6e684c6450767e055ba7717",
                "reference": "e12d55f74a8cca18c6e684c6450767e055ba7717",
                "shasum": ""
            },
            "require": {
                "php": "^7.1 || ^8.0",
                "phpstan/phpstan": "^1.2.0"
            },
            "require-dev": {
                "nikic/php-parser": "^4.13.0",
                "php-parallel-lint/php-parallel-lint": "^1.2",
                "phpstan/phpstan-phpunit": "^1.0",
                "phpunit/phpunit": "^9.5"
            },
            "type": "phpstan-extension",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0-dev"
                },
                "phpstan": {
                    "includes": [
                        "rules.neon"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "PHPStan\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Extra strict and opinionated rules for PHPStan",
            "support": {
                "issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
                "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.1.0"
            },
            "time": "2021-11-18T09:30:29+00:00"
        },
        {
            "name": "phpunit/php-code-coverage",
            "version": "9.2.15",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
                "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
                "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-libxml": "*",
                "ext-xmlwriter": "*",
                "nikic/php-parser": "^4.13.0",
                "php": ">=7.3",
                "phpunit/php-file-iterator": "^3.0.3",
                "phpunit/php-text-template": "^2.0.2",
                "sebastian/code-unit-reverse-lookup": "^2.0.2",
                "sebastian/complexity": "^2.0",
                "sebastian/environment": "^5.1.2",
                "sebastian/lines-of-code": "^1.0.3",
                "sebastian/version": "^3.0.1",
                "theseer/tokenizer": "^1.2.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "suggest": {
                "ext-pcov": "*",
                "ext-xdebug": "*"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "9.2-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
            "keywords": [
                "coverage",
                "testing",
                "xunit"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2022-03-07T09:28:20+00:00"
        },
        {
            "name": "phpunit/php-file-iterator",
            "version": "3.0.6",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
                "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
                "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
            "keywords": [
                "filesystem",
                "iterator"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
                "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2021-12-02T12:48:52+00:00"
        },
        {
            "name": "phpunit/php-invoker",
            "version": "3.1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-invoker.git",
                "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
                "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "ext-pcntl": "*",
                "phpunit/phpunit": "^9.3"
            },
            "suggest": {
                "ext-pcntl": "*"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.1-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Invoke callables with a timeout",
            "homepage": "https://github.com/sebastianbergmann/php-invoker/",
            "keywords": [
                "process"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
                "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-09-28T05:58:55+00:00"
        },
        {
            "name": "phpunit/php-text-template",
            "version": "2.0.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-text-template.git",
                "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
                "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Simple template engine.",
            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
            "keywords": [
                "template"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
                "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T05:33:50+00:00"
        },
        {
            "name": "phpunit/php-timer",
            "version": "5.0.3",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-timer.git",
                "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
                "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "5.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Utility class for timing",
            "homepage": "https://github.com/sebastianbergmann/php-timer/",
            "keywords": [
                "timer"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/php-timer/issues",
                "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T13:16:10+00:00"
        },
        {
            "name": "phpunit/phpunit",
            "version": "9.5.20",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit.git",
                "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba",
                "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba",
                "shasum": ""
            },
            "require": {
                "doctrine/instantiator": "^1.3.1",
                "ext-dom": "*",
                "ext-json": "*",
                "ext-libxml": "*",
                "ext-mbstring": "*",
                "ext-xml": "*",
                "ext-xmlwriter": "*",
                "myclabs/deep-copy": "^1.10.1",
                "phar-io/manifest": "^2.0.3",
                "phar-io/version": "^3.0.2",
                "php": ">=7.3",
                "phpspec/prophecy": "^1.12.1",
                "phpunit/php-code-coverage": "^9.2.13",
                "phpunit/php-file-iterator": "^3.0.5",
                "phpunit/php-invoker": "^3.1.1",
                "phpunit/php-text-template": "^2.0.3",
                "phpunit/php-timer": "^5.0.2",
                "sebastian/cli-parser": "^1.0.1",
                "sebastian/code-unit": "^1.0.6",
                "sebastian/comparator": "^4.0.5",
                "sebastian/diff": "^4.0.3",
                "sebastian/environment": "^5.1.3",
                "sebastian/exporter": "^4.0.3",
                "sebastian/global-state": "^5.0.1",
                "sebastian/object-enumerator": "^4.0.3",
                "sebastian/resource-operations": "^3.0.3",
                "sebastian/type": "^3.0",
                "sebastian/version": "^3.0.2"
            },
            "require-dev": {
                "ext-pdo": "*",
                "phpspec/prophecy-phpunit": "^2.0.1"
            },
            "suggest": {
                "ext-soap": "*",
                "ext-xdebug": "*"
            },
            "bin": [
                "phpunit"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "9.5-dev"
                }
            },
            "autoload": {
                "files": [
                    "src/Framework/Assert/Functions.php"
                ],
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "The PHP Unit Testing framework.",
            "homepage": "https://phpunit.de/",
            "keywords": [
                "phpunit",
                "testing",
                "xunit"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/phpunit/issues",
                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20"
            },
            "funding": [
                {
                    "url": "https://phpunit.de/sponsors.html",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2022-04-01T12:37:26+00:00"
        },
        {
            "name": "psr/container",
            "version": "1.1.2",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/container.git",
                "reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
                "reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4.0"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Psr\\Container\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "https://www.php-fig.org/"
                }
            ],
            "description": "Common Container Interface (PHP FIG PSR-11)",
            "homepage": "https://github.com/php-fig/container",
            "keywords": [
                "PSR-11",
                "container",
                "container-interface",
                "container-interop",
                "psr"
            ],
            "support": {
                "issues": "https://github.com/php-fig/container/issues",
                "source": "https://github.com/php-fig/container/tree/1.1.2"
            },
            "time": "2021-11-05T16:50:12+00:00"
        },
        {
            "name": "psr/log",
            "version": "2.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/log.git",
                "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376",
                "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376",
                "shasum": ""
            },
            "require": {
                "php": ">=8.0.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.0.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Psr\\Log\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "https://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging libraries",
            "homepage": "https://github.com/php-fig/log",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "support": {
                "source": "https://github.com/php-fig/log/tree/2.0.0"
            },
            "time": "2021-07-14T16:41:46+00:00"
        },
        {
            "name": "sanmai/later",
            "version": "0.1.2",
            "source": {
                "type": "git",
                "url": "https://github.com/sanmai/later.git",
                "reference": "9b659fecef2030193fd02402955bc39629d5606f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sanmai/later/zipball/9b659fecef2030193fd02402955bc39629d5606f",
                "reference": "9b659fecef2030193fd02402955bc39629d5606f",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "^2.13",
                "infection/infection": ">=0.10.5",
                "phan/phan": ">=2",
                "php-coveralls/php-coveralls": "^2.0",
                "phpstan/phpstan": ">=0.10",
                "phpunit/phpunit": ">=7.4",
                "vimeo/psalm": ">=2"
            },
            "type": "library",
            "autoload": {
                "files": [
                    "src/functions.php"
                ],
                "psr-4": {
                    "Later\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "Apache-2.0"
            ],
            "authors": [
                {
                    "name": "Alexey Kopytko",
                    "email": "alexey@kopytko.com"
                }
            ],
            "description": "Later: deferred wrapper object",
            "support": {
                "issues": "https://github.com/sanmai/later/issues",
                "source": "https://github.com/sanmai/later/tree/0.1.2"
            },
            "funding": [
                {
                    "url": "https://github.com/sanmai",
                    "type": "github"
                }
            ],
            "time": "2021-01-02T10:26:44+00:00"
        },
        {
            "name": "sanmai/pipeline",
            "version": "v6.1",
            "source": {
                "type": "git",
                "url": "https://github.com/sanmai/pipeline.git",
                "reference": "3a88f2617237e18d5cd2aa38ca3d4b22770306c2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sanmai/pipeline/zipball/3a88f2617237e18d5cd2aa38ca3d4b22770306c2",
                "reference": "3a88f2617237e18d5cd2aa38ca3d4b22770306c2",
                "shasum": ""
            },
            "require": {
                "php": "^7.1 || ^8.0"
            },
            "require-dev": {
                "ergebnis/composer-normalize": "^2.8",
                "friendsofphp/php-cs-fixer": "^3",
                "infection/infection": ">=0.10.5",
                "league/pipeline": "^1.0 || ^0.3",
                "phan/phan": ">=1.1",
                "php-coveralls/php-coveralls": "^2.4.1",
                "phpstan/phpstan": ">=0.10",
                "phpunit/phpunit": "^7.4 || ^8.1 || ^9.4",
                "vimeo/psalm": ">=2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "v6.x-dev"
                }
            },
            "autoload": {
                "files": [
                    "src/functions.php"
                ],
                "psr-4": {
                    "Pipeline\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "Apache-2.0"
            ],
            "authors": [
                {
                    "name": "Alexey Kopytko",
                    "email": "alexey@kopytko.com"
                }
            ],
            "description": "General-purpose collections pipeline",
            "support": {
                "issues": "https://github.com/sanmai/pipeline/issues",
                "source": "https://github.com/sanmai/pipeline/tree/v6.1"
            },
            "funding": [
                {
                    "url": "https://github.com/sanmai",
                    "type": "github"
                }
            ],
            "time": "2022-01-30T08:15:59+00:00"
        },
        {
            "name": "sebastian/cli-parser",
            "version": "1.0.1",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/cli-parser.git",
                "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
                "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Library for parsing CLI options",
            "homepage": "https://github.com/sebastianbergmann/cli-parser",
            "support": {
                "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
                "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-09-28T06:08:49+00:00"
        },
        {
            "name": "sebastian/code-unit",
            "version": "1.0.8",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/code-unit.git",
                "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
                "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Collection of value objects that represent the PHP code units",
            "homepage": "https://github.com/sebastianbergmann/code-unit",
            "support": {
                "issues": "https://github.com/sebastianbergmann/code-unit/issues",
                "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T13:08:54+00:00"
        },
        {
            "name": "sebastian/code-unit-reverse-lookup",
            "version": "2.0.3",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
                "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
                "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                }
            ],
            "description": "Looks up which function or method a line of code belongs to",
            "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
            "support": {
                "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
                "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-09-28T05:30:19+00:00"
        },
        {
            "name": "sebastian/comparator",
            "version": "4.0.6",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/comparator.git",
                "reference": "55f4261989e546dc112258c7a75935a81a7ce382"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
                "reference": "55f4261989e546dc112258c7a75935a81a7ce382",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3",
                "sebastian/diff": "^4.0",
                "sebastian/exporter": "^4.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                },
                {
                    "name": "Jeff Welch",
                    "email": "whatthejeff@gmail.com"
                },
                {
                    "name": "Volker Dusch",
                    "email": "github@wallbash.com"
                },
                {
                    "name": "Bernhard Schussek",
                    "email": "bschussek@2bepublished.at"
                }
            ],
            "description": "Provides the functionality to compare PHP values for equality",
            "homepage": "https://github.com/sebastianbergmann/comparator",
            "keywords": [
                "comparator",
                "compare",
                "equality"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/comparator/issues",
                "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T15:49:45+00:00"
        },
        {
            "name": "sebastian/complexity",
            "version": "2.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/complexity.git",
                "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
                "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
                "shasum": ""
            },
            "require": {
                "nikic/php-parser": "^4.7",
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Library for calculating the complexity of PHP code units",
            "homepage": "https://github.com/sebastianbergmann/complexity",
            "support": {
                "issues": "https://github.com/sebastianbergmann/complexity/issues",
                "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T15:52:27+00:00"
        },
        {
            "name": "sebastian/diff",
            "version": "4.0.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/diff.git",
                "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
                "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3",
                "symfony/process": "^4.2 || ^5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                },
                {
                    "name": "Kore Nordmann",
                    "email": "mail@kore-nordmann.de"
                }
            ],
            "description": "Diff implementation",
            "homepage": "https://github.com/sebastianbergmann/diff",
            "keywords": [
                "diff",
                "udiff",
                "unidiff",
                "unified diff"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/diff/issues",
                "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T13:10:38+00:00"
        },
        {
            "name": "sebastian/environment",
            "version": "5.1.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/environment.git",
                "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
                "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "suggest": {
                "ext-posix": "*"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "5.1-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                }
            ],
            "description": "Provides functionality to handle HHVM/PHP environments",
            "homepage": "http://www.github.com/sebastianbergmann/environment",
            "keywords": [
                "Xdebug",
                "environment",
                "hhvm"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/environment/issues",
                "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2022-04-03T09:37:03+00:00"
        },
        {
            "name": "sebastian/exporter",
            "version": "4.0.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/exporter.git",
                "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9",
                "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3",
                "sebastian/recursion-context": "^4.0"
            },
            "require-dev": {
                "ext-mbstring": "*",
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                },
                {
                    "name": "Jeff Welch",
                    "email": "whatthejeff@gmail.com"
                },
                {
                    "name": "Volker Dusch",
                    "email": "github@wallbash.com"
                },
                {
                    "name": "Adam Harvey",
                    "email": "aharvey@php.net"
                },
                {
                    "name": "Bernhard Schussek",
                    "email": "bschussek@gmail.com"
                }
            ],
            "description": "Provides the functionality to export PHP variables for visualization",
            "homepage": "https://www.github.com/sebastianbergmann/exporter",
            "keywords": [
                "export",
                "exporter"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/exporter/issues",
                "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2021-11-11T14:18:36+00:00"
        },
        {
            "name": "sebastian/global-state",
            "version": "5.0.5",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/global-state.git",
                "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
                "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3",
                "sebastian/object-reflector": "^2.0",
                "sebastian/recursion-context": "^4.0"
            },
            "require-dev": {
                "ext-dom": "*",
                "phpunit/phpunit": "^9.3"
            },
            "suggest": {
                "ext-uopz": "*"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "5.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                }
            ],
            "description": "Snapshotting of global state",
            "homepage": "http://www.github.com/sebastianbergmann/global-state",
            "keywords": [
                "global state"
            ],
            "support": {
                "issues": "https://github.com/sebastianbergmann/global-state/issues",
                "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2022-02-14T08:28:10+00:00"
        },
        {
            "name": "sebastian/lines-of-code",
            "version": "1.0.3",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/lines-of-code.git",
                "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
                "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
                "shasum": ""
            },
            "require": {
                "nikic/php-parser": "^4.6",
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Library for counting the lines of code in PHP source code",
            "homepage": "https://github.com/sebastianbergmann/lines-of-code",
            "support": {
                "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
                "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-11-28T06:42:11+00:00"
        },
        {
            "name": "sebastian/object-enumerator",
            "version": "4.0.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/object-enumerator.git",
                "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
                "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3",
                "sebastian/object-reflector": "^2.0",
                "sebastian/recursion-context": "^4.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                }
            ],
            "description": "Traverses array structures and object graphs to enumerate all referenced objects",
            "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
            "support": {
                "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
                "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T13:12:34+00:00"
        },
        {
            "name": "sebastian/object-reflector",
            "version": "2.0.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/object-reflector.git",
                "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
                "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                }
            ],
            "description": "Allows reflection of object attributes, including inherited and non-public ones",
            "homepage": "https://github.com/sebastianbergmann/object-reflector/",
            "support": {
                "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
                "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T13:14:26+00:00"
        },
        {
            "name": "sebastian/recursion-context",
            "version": "4.0.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/recursion-context.git",
                "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
                "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                },
                {
                    "name": "Jeff Welch",
                    "email": "whatthejeff@gmail.com"
                },
                {
                    "name": "Adam Harvey",
                    "email": "aharvey@php.net"
                }
            ],
            "description": "Provides functionality to recursively process PHP variables",
            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
            "support": {
                "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
                "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-10-26T13:17:30+00:00"
        },
        {
            "name": "sebastian/resource-operations",
            "version": "3.0.3",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/resource-operations.git",
                "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
                "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de"
                }
            ],
            "description": "Provides a list of PHP built-in functions that operate on resources",
            "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
            "support": {
                "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
                "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-09-28T06:45:17+00:00"
        },
        {
            "name": "sebastian/type",
            "version": "3.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/type.git",
                "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
                "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^9.5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Collection of value objects that represent the types of the PHP type system",
            "homepage": "https://github.com/sebastianbergmann/type",
            "support": {
                "issues": "https://github.com/sebastianbergmann/type/issues",
                "source": "https://github.com/sebastianbergmann/type/tree/3.0.0"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2022-03-15T09:54:48+00:00"
        },
        {
            "name": "sebastian/version",
            "version": "3.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/version.git",
                "reference": "c6c1022351a901512170118436c764e473f6de8c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
                "reference": "c6c1022351a901512170118436c764e473f6de8c",
                "shasum": ""
            },
            "require": {
                "php": ">=7.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "Library that helps with managing the version number of Git-hosted PHP projects",
            "homepage": "https://github.com/sebastianbergmann/version",
            "support": {
                "issues": "https://github.com/sebastianbergmann/version/issues",
                "source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
            },
            "funding": [
                {
                    "url": "https://github.com/sebastianbergmann",
                    "type": "github"
                }
            ],
            "time": "2020-09-28T06:39:44+00:00"
        },
        {
            "name": "seld/jsonlint",
            "version": "1.9.0",
            "source": {
                "type": "git",
                "url": "https://github.com/Seldaek/jsonlint.git",
                "reference": "4211420d25eba80712bff236a98960ef68b866b7"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7",
                "reference": "4211420d25eba80712bff236a98960ef68b866b7",
                "shasum": ""
            },
            "require": {
                "php": "^5.3 || ^7.0 || ^8.0"
            },
            "require-dev": {
                "phpstan/phpstan": "^1.5",
                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
            },
            "bin": [
                "bin/jsonlint"
            ],
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Seld\\JsonLint\\": "src/Seld/JsonLint/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be"
                }
            ],
            "description": "JSON Linter",
            "keywords": [
                "json",
                "linter",
                "parser",
                "validator"
            ],
            "support": {
                "issues": "https://github.com/Seldaek/jsonlint/issues",
                "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0"
            },
            "funding": [
                {
                    "url": "https://github.com/Seldaek",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
                    "type": "tidelift"
                }
            ],
            "time": "2022-04-01T13:37:23+00:00"
        },
        {
            "name": "squizlabs/php_codesniffer",
            "version": "3.6.2",
            "source": {
                "type": "git",
                "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
                "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
                "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
                "shasum": ""
            },
            "require": {
                "ext-simplexml": "*",
                "ext-tokenizer": "*",
                "ext-xmlwriter": "*",
                "php": ">=5.4.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
            },
            "bin": [
                "bin/phpcs",
                "bin/phpcbf"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.x-dev"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Greg Sherwood",
                    "role": "lead"
                }
            ],
            "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
            "homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
            "keywords": [
                "phpcs",
                "standards"
            ],
            "support": {
                "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
                "source": "https://github.com/squizlabs/PHP_CodeSniffer",
                "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
            },
            "time": "2021-12-12T21:44:58+00:00"
        },
        {
            "name": "symfony/console",
            "version": "v5.4.7",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/console.git",
                "reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/console/zipball/900275254f0a1a2afff1ab0e11abd5587a10e1d6",
                "reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/deprecation-contracts": "^2.1|^3",
                "symfony/polyfill-mbstring": "~1.0",
                "symfony/polyfill-php73": "^1.9",
                "symfony/polyfill-php80": "^1.16",
                "symfony/service-contracts": "^1.1|^2|^3",
                "symfony/string": "^5.1|^6.0"
            },
            "conflict": {
                "psr/log": ">=3",
                "symfony/dependency-injection": "<4.4",
                "symfony/dotenv": "<5.1",
                "symfony/event-dispatcher": "<4.4",
                "symfony/lock": "<4.4",
                "symfony/process": "<4.4"
            },
            "provide": {
                "psr/log-implementation": "1.0|2.0"
            },
            "require-dev": {
                "psr/log": "^1|^2",
                "symfony/config": "^4.4|^5.0|^6.0",
                "symfony/dependency-injection": "^4.4|^5.0|^6.0",
                "symfony/event-dispatcher": "^4.4|^5.0|^6.0",
                "symfony/lock": "^4.4|^5.0|^6.0",
                "symfony/process": "^4.4|^5.0|^6.0",
                "symfony/var-dumper": "^4.4|^5.0|^6.0"
            },
            "suggest": {
                "psr/log": "For using the console logger",
                "symfony/event-dispatcher": "",
                "symfony/lock": "",
                "symfony/process": ""
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Console\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Eases the creation of beautiful and testable command line interfaces",
            "homepage": "https://symfony.com",
            "keywords": [
                "cli",
                "command line",
                "console",
                "terminal"
            ],
            "support": {
                "source": "https://github.com/symfony/console/tree/v5.4.7"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-03-31T17:09:19+00:00"
        },
        {
            "name": "symfony/deprecation-contracts",
            "version": "v2.5.1",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/deprecation-contracts.git",
                "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
                "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "2.5-dev"
                },
                "thanks": {
                    "name": "symfony/contracts",
                    "url": "https://github.com/symfony/contracts"
                }
            },
            "autoload": {
                "files": [
                    "function.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "A generic function and convention to trigger deprecation notices",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-01-02T09:53:40+00:00"
        },
        {
            "name": "symfony/filesystem",
            "version": "v5.4.7",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/filesystem.git",
                "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/filesystem/zipball/3a4442138d80c9f7b600fb297534ac718b61d37f",
                "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/polyfill-ctype": "~1.8",
                "symfony/polyfill-mbstring": "~1.8",
                "symfony/polyfill-php80": "^1.16"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Filesystem\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Provides basic utilities for the filesystem",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/filesystem/tree/v5.4.7"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-04-01T12:33:59+00:00"
        },
        {
            "name": "symfony/finder",
            "version": "v5.4.3",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/finder.git",
                "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/finder/zipball/231313534dded84c7ecaa79d14bc5da4ccb69b7d",
                "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/deprecation-contracts": "^2.1|^3",
                "symfony/polyfill-php80": "^1.16"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Finder\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Finds files and directories via an intuitive fluent interface",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/finder/tree/v5.4.3"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-01-26T16:34:36+00:00"
        },
        {
            "name": "symfony/polyfill-ctype",
            "version": "v1.25.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-ctype.git",
                "reference": "30885182c981ab175d4d034db0f6f469898070ab"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
                "reference": "30885182c981ab175d4d034db0f6f469898070ab",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "provide": {
                "ext-ctype": "*"
            },
            "suggest": {
                "ext-ctype": "For best performance"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Ctype\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Gert de Pagter",
                    "email": "BackEndTea@gmail.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for ctype functions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "ctype",
                "polyfill",
                "portable"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2021-10-20T20:35:02+00:00"
        },
        {
            "name": "symfony/polyfill-intl-grapheme",
            "version": "v1.25.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
                "reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
                "reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "suggest": {
                "ext-intl": "For best performance"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for intl's grapheme_* functions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "grapheme",
                "intl",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2021-11-23T21:10:46+00:00"
        },
        {
            "name": "symfony/polyfill-intl-normalizer",
            "version": "v1.25.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
                "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "suggest": {
                "ext-intl": "For best performance"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for intl's Normalizer class and related functions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "intl",
                "normalizer",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2021-02-19T12:13:01+00:00"
        },
        {
            "name": "symfony/polyfill-mbstring",
            "version": "v1.25.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-mbstring.git",
                "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
                "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "provide": {
                "ext-mbstring": "*"
            },
            "suggest": {
                "ext-mbstring": "For best performance"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Mbstring\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for the Mbstring extension",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "mbstring",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2021-11-30T18:21:41+00:00"
        },
        {
            "name": "symfony/polyfill-php73",
            "version": "v1.25.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-php73.git",
                "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5",
                "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Php73\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2021-06-05T21:20:04+00:00"
        },
        {
            "name": "symfony/polyfill-php80",
            "version": "v1.25.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-php80.git",
                "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
                "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "autoload": {
                "files": [
                    "bootstrap.php"
                ],
                "psr-4": {
                    "Symfony\\Polyfill\\Php80\\": ""
                },
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Ion Bazan",
                    "email": "ion.bazan@gmail.com"
                },
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-03-04T08:16:47+00:00"
        },
        {
            "name": "symfony/process",
            "version": "v5.4.7",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/process.git",
                "reference": "38a44b2517b470a436e1c944bf9b9ba3961137fb"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/process/zipball/38a44b2517b470a436e1c944bf9b9ba3961137fb",
                "reference": "38a44b2517b470a436e1c944bf9b9ba3961137fb",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/polyfill-php80": "^1.16"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Process\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Executes commands in sub-processes",
            "homepage": "https://symfony.com",
            "support": {
                "source": "https://github.com/symfony/process/tree/v5.4.7"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-03-18T16:18:52+00:00"
        },
        {
            "name": "symfony/service-contracts",
            "version": "v2.5.1",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/service-contracts.git",
                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
                "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "psr/container": "^1.1",
                "symfony/deprecation-contracts": "^2.1|^3"
            },
            "conflict": {
                "ext-psr": "<1.1|>=2"
            },
            "suggest": {
                "symfony/service-implementation": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "2.5-dev"
                },
                "thanks": {
                    "name": "symfony/contracts",
                    "url": "https://github.com/symfony/contracts"
                }
            },
            "autoload": {
                "psr-4": {
                    "Symfony\\Contracts\\Service\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Generic abstractions related to writing services",
            "homepage": "https://symfony.com",
            "keywords": [
                "abstractions",
                "contracts",
                "decoupling",
                "interfaces",
                "interoperability",
                "standards"
            ],
            "support": {
                "source": "https://github.com/symfony/service-contracts/tree/v2.5.1"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-03-13T20:07:29+00:00"
        },
        {
            "name": "symfony/string",
            "version": "v5.4.3",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/string.git",
                "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10",
                "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2.5",
                "symfony/polyfill-ctype": "~1.8",
                "symfony/polyfill-intl-grapheme": "~1.0",
                "symfony/polyfill-intl-normalizer": "~1.0",
                "symfony/polyfill-mbstring": "~1.0",
                "symfony/polyfill-php80": "~1.15"
            },
            "conflict": {
                "symfony/translation-contracts": ">=3.0"
            },
            "require-dev": {
                "symfony/error-handler": "^4.4|^5.0|^6.0",
                "symfony/http-client": "^4.4|^5.0|^6.0",
                "symfony/translation-contracts": "^1.1|^2",
                "symfony/var-exporter": "^4.4|^5.0|^6.0"
            },
            "type": "library",
            "autoload": {
                "files": [
                    "Resources/functions.php"
                ],
                "psr-4": {
                    "Symfony\\Component\\String\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
            "homepage": "https://symfony.com",
            "keywords": [
                "grapheme",
                "i18n",
                "string",
                "unicode",
                "utf-8",
                "utf8"
            ],
            "support": {
                "source": "https://github.com/symfony/string/tree/v5.4.3"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "time": "2022-01-02T09:53:40+00:00"
        },
        {
            "name": "thecodingmachine/safe",
            "version": "v1.3.3",
            "source": {
                "type": "git",
                "url": "https://github.com/thecodingmachine/safe.git",
                "reference": "a8ab0876305a4cdaef31b2350fcb9811b5608dbc"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/a8ab0876305a4cdaef31b2350fcb9811b5608dbc",
                "reference": "a8ab0876305a4cdaef31b2350fcb9811b5608dbc",
                "shasum": ""
            },
            "require": {
                "php": ">=7.2"
            },
            "require-dev": {
                "phpstan/phpstan": "^0.12",
                "squizlabs/php_codesniffer": "^3.2",
                "thecodingmachine/phpstan-strict-rules": "^0.12"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "0.1-dev"
                }
            },
            "autoload": {
                "files": [
                    "deprecated/apc.php",
                    "deprecated/libevent.php",
                    "deprecated/mssql.php",
                    "deprecated/stats.php",
                    "lib/special_cases.php",
                    "generated/apache.php",
                    "generated/apcu.php",
                    "generated/array.php",
                    "generated/bzip2.php",
                    "generated/calendar.php",
                    "generated/classobj.php",
                    "generated/com.php",
                    "generated/cubrid.php",
                    "generated/curl.php",
                    "generated/datetime.php",
                    "generated/dir.php",
                    "generated/eio.php",
                    "generated/errorfunc.php",
                    "generated/exec.php",
                    "generated/fileinfo.php",
                    "generated/filesystem.php",
                    "generated/filter.php",
                    "generated/fpm.php",
                    "generated/ftp.php",
                    "generated/funchand.php",
                    "generated/gmp.php",
                    "generated/gnupg.php",
                    "generated/hash.php",
                    "generated/ibase.php",
                    "generated/ibmDb2.php",
                    "generated/iconv.php",
                    "generated/image.php",
                    "generated/imap.php",
                    "generated/info.php",
                    "generated/ingres-ii.php",
                    "generated/inotify.php",
                    "generated/json.php",
                    "generated/ldap.php",
                    "generated/libxml.php",
                    "generated/lzf.php",
                    "generated/mailparse.php",
                    "generated/mbstring.php",
                    "generated/misc.php",
                    "generated/msql.php",
                    "generated/mysql.php",
                    "generated/mysqli.php",
                    "generated/mysqlndMs.php",
                    "generated/mysqlndQc.php",
                    "generated/network.php",
                    "generated/oci8.php",
                    "generated/opcache.php",
                    "generated/openssl.php",
                    "generated/outcontrol.php",
                    "generated/password.php",
                    "generated/pcntl.php",
                    "generated/pcre.php",
                    "generated/pdf.php",
                    "generated/pgsql.php",
                    "generated/posix.php",
                    "generated/ps.php",
                    "generated/pspell.php",
                    "generated/readline.php",
                    "generated/rpminfo.php",
                    "generated/rrd.php",
                    "generated/sem.php",
                    "generated/session.php",
                    "generated/shmop.php",
                    "generated/simplexml.php",
                    "generated/sockets.php",
                    "generated/sodium.php",
                    "generated/solr.php",
                    "generated/spl.php",
                    "generated/sqlsrv.php",
                    "generated/ssdeep.php",
                    "generated/ssh2.php",
                    "generated/stream.php",
                    "generated/strings.php",
                    "generated/swoole.php",
                    "generated/uodbc.php",
                    "generated/uopz.php",
                    "generated/url.php",
                    "generated/var.php",
                    "generated/xdiff.php",
                    "generated/xml.php",
                    "generated/xmlrpc.php",
                    "generated/yaml.php",
                    "generated/yaz.php",
                    "generated/zip.php",
                    "generated/zlib.php"
                ],
                "psr-4": {
                    "Safe\\": [
                        "lib/",
                        "deprecated/",
                        "generated/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "PHP core functions that throw exceptions instead of returning FALSE on error",
            "support": {
                "issues": "https://github.com/thecodingmachine/safe/issues",
                "source": "https://github.com/thecodingmachine/safe/tree/v1.3.3"
            },
            "time": "2020-10-28T17:51:34+00:00"
        },
        {
            "name": "theseer/tokenizer",
            "version": "1.2.1",
            "source": {
                "type": "git",
                "url": "https://github.com/theseer/tokenizer.git",
                "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
                "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-tokenizer": "*",
                "ext-xmlwriter": "*",
                "php": "^7.2 || ^8.0"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Arne Blankerts",
                    "email": "arne@blankerts.de",
                    "role": "Developer"
                }
            ],
            "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
            "support": {
                "issues": "https://github.com/theseer/tokenizer/issues",
                "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
            },
            "funding": [
                {
                    "url": "https://github.com/theseer",
                    "type": "github"
                }
            ],
            "time": "2021-07-28T10:34:58+00:00"
        },
        {
            "name": "webmozart/assert",
            "version": "1.10.0",
            "source": {
                "type": "git",
                "url": "https://github.com/webmozarts/assert.git",
                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
                "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
                "shasum": ""
            },
            "require": {
                "php": "^7.2 || ^8.0",
                "symfony/polyfill-ctype": "^1.8"
            },
            "conflict": {
                "phpstan/phpstan": "<0.12.20",
                "vimeo/psalm": "<4.6.1 || 4.6.2"
            },
            "require-dev": {
                "phpunit/phpunit": "^8.5.13"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.10-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Webmozart\\Assert\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Bernhard Schussek",
                    "email": "bschussek@gmail.com"
                }
            ],
            "description": "Assertions to validate method input/output with nice error messages.",
            "keywords": [
                "assert",
                "check",
                "validate"
            ],
            "support": {
                "issues": "https://github.com/webmozarts/assert/issues",
                "source": "https://github.com/webmozarts/assert/tree/1.10.0"
            },
            "time": "2021-03-09T10:59:23+00:00"
        },
        {
            "name": "webmozart/path-util",
            "version": "2.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/webmozart/path-util.git",
                "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
                "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "webmozart/assert": "~1.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^4.6",
                "sebastian/version": "^1.0.1"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Webmozart\\PathUtil\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Bernhard Schussek",
                    "email": "bschussek@gmail.com"
                }
            ],
            "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
            "support": {
                "issues": "https://github.com/webmozart/path-util/issues",
                "source": "https://github.com/webmozart/path-util/tree/2.3.0"
            },
            "abandoned": "symfony/filesystem",
            "time": "2015-12-17T08:42:14+00:00"
        }
    ],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": {
        "php": "^8.0"
    },
    "platform-dev": [],
    "platform-overrides": {
        "php": "8.0"
    },
    "plugin-api-version": "2.3.0"
}

A  => infection.json +14 -0
@@ 1,14 @@
{
    "timeout": 10,
    "source": {
        "directories": [
            "src"
        ]
    },
    "logs": {
        "text": "var/infection.log"
    },
    "mutators": {
        "@default": true
    }
}

A  => phpcs.xml +19 -0
@@ 1,19 @@
<?xml version="1.0"?>
<ruleset name="Ancarda Coding Style">
    <arg value="p"/>
    <arg name="colors"/>

    <rule ref="PSR12" />
    <rule ref="Generic.CodeAnalysis.AssignmentInCondition" />
    <rule ref="Generic.CodeAnalysis.EmptyPHPStatement" />
    <rule ref="Generic.CodeAnalysis.EmptyStatement" />
    <rule ref="Generic.CodeAnalysis.JumbledIncrementer" />
    <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier" />
    <rule ref="Generic.ControlStructures.DisallowYodaConditions" />
    <rule ref="Generic.Files.ExecutableFile" />
    <rule ref="Generic.PHP.RequireStrictTypes" />
    <rule ref="Generic.VersionControl.GitMergeConflict" />

    <file>src</file>
    <file>tests</file>
</ruleset>

A  => phpstan.neon +14 -0
@@ 1,14 @@
parameters:
	level: max
	paths:
		- src
		- tests
	ignoreErrors:
		- '/^Call to an undefined method Ancarda\\Gemini\\Gemtext\\Node\\Node::(getText|getLink|getLabel)/'
		- '/^Parameter #1 \$pre of method Ancarda\\Gemini\\Gemtext\\Encoder\\HTML::preformatted\(\) expects Ancarda\\Gemini\\Gemtext\\Node\\Preformatted, Ancarda\\Gemini\\Gemtext\\Node\\Node given/'

includes:
	- vendor/phpstan/phpstan-phpunit/extension.neon
	- vendor/phpstan/phpstan-phpunit/rules.neon
	- vendor/phpstan/phpstan-strict-rules/rules.neon
	- vendor/phpstan/phpstan/conf/bleedingEdge.neon

A  => phpunit.xml +29 -0
@@ 1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
	beStrictAboutChangesToGlobalState="true"
	beStrictAboutOutputDuringTests="true"
	beStrictAboutTestsThatDoNotTestAnything="true"
	bootstrap="vendor/autoload.php"
	cacheResultFile="var/phpunit-result-cache"
	colors="true"
	convertErrorsToExceptions="true"
	convertNoticesToExceptions="true"
	convertWarningsToExceptions="true"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
	<coverage processUncoveredFiles="true">
		<include>
			<directory suffix=".php">src</directory>
		</include>
		<report>
			<html outputDirectory="var/coverage"/>
			<text outputFile="php://stdout" showOnlySummary="true"/>
			<clover outputFile="var/coverage/coverage.clover.xml"/>
		</report>
	</coverage>
	<testsuites>
		<testsuite name="Unit Tests">
			<directory>tests</directory>
		</testsuite>
	</testsuites>
</phpunit>

A  => src/Encoder/EncoderException.php +9 -0
@@ 1,9 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Encoder;

abstract class EncoderException extends \RuntimeException
{
}

A  => src/Encoder/EncoderInterface.php +17 -0
@@ 1,17 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Encoder;

use Ancarda\Gemini\Gemtext\Node\Node;

interface EncoderInterface
{
    /**
     * @param iterable<Node> $nodes
     * @throws EncoderException
     * @return \Generator<string>
     */
    public function encode(iterable $nodes): \Generator;
}

A  => src/Encoder/HTML.php +119 -0
@@ 1,119 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Encoder;

use Ancarda\Gemini\Gemtext\Node\Blockquote;
use Ancarda\Gemini\Gemtext\Node\H1;
use Ancarda\Gemini\Gemtext\Node\H2;
use Ancarda\Gemini\Gemtext\Node\H3;
use Ancarda\Gemini\Gemtext\Node\Link;
use Ancarda\Gemini\Gemtext\Node\ListElement;
use Ancarda\Gemini\Gemtext\Node\Paragraph;
use Ancarda\Gemini\Gemtext\Node\Preformatted;
use Generator;
use LogicException;

final class HTML implements EncoderInterface
{
    public const PRE_CAPTION_IGNORE = 0;
    public const PRE_CAPTION_AS_CSS = 1;
    public const PRE_CAPTION_AS_ARIA_LABEL = 2;

    private int $preCaptionBehavior = self::PRE_CAPTION_IGNORE;

    /**
     * @param int $flags Bitwise number made up using PRE_CAPTION_
     * @throws LogicException Invalid number
     */
    public function setPreCaptionBehavior(int $flags): void
    {
        if ($flags < 0 || $flags > 3) {
            throw new LogicException('Invalid behavior code: ' . $flags);
        }

        $this->preCaptionBehavior = $flags;
    }

    /**
     * Reset generator back to initial configuration
     */
    public function reset(): void
    {
        $this->preCaptionBehavior = self::PRE_CAPTION_IGNORE;
    }

    public function encode(iterable $nodes): Generator
    {
        $inList = false;

        foreach ($nodes as $node) {
            $class = get_class($node);

            // Outside of a list, an initial ListElement will cause a <ul> to emerge.
            if ($class === ListElement::class && !$inList) {
                $inList = true;
                yield '<ul>';
            }

            // Inside a list, anything other than a ListElement will terminate the <ul>
            if ($inList && $class !== ListElement::class) {
                $inList = false;
                yield '</ul>';
            }

            yield match ($class) {
                // Text
                Paragraph::class => '<p>' . htmlspecialchars($node->getText(), ENT_HTML5) . '</p>',

                // Links
                Link::class => sprintf(
                    '<p><a href="%s">%s</a></p>',
                    htmlspecialchars($node->getLink(), ENT_HTML5),
                    htmlspecialchars($node->getLabel() === null ? $node->getLink() : $node->getLabel(), ENT_HTML5),
                ),

                // Headings
                H1::class => '<h1>' . htmlspecialchars($node->getText(), ENT_HTML5) . '</h1>',
                H2::class => '<h2>' . htmlspecialchars($node->getText(), ENT_HTML5) . '</h2>',
                H3::class => '<h3>' . htmlspecialchars($node->getText(), ENT_HTML5) . '</h3>',

                // Lists
                ListElement::class => '<li>' . htmlspecialchars($node->getText(), ENT_HTML5) . '</li>',

                // Blockquotes
                Blockquote::class => '<blockquote>' . htmlspecialchars($node->getText(), ENT_HTML5) . '</blockquote>',

                // Preformatted Text
                Preformatted::class => self::preformatted($node),

                default => throw new UnsupportedNodeException($node),
            };
        }

        // If the very last node is a ListElement, the <ul> tag must be closed.
        if ($inList) {
            yield '</ul>';
        }
    }

    private function preformatted(Preformatted $pre): string
    {
        $tag = '';

        if (($this->preCaptionBehavior & self::PRE_CAPTION_AS_CSS) > 0) {
            $tag = ' class="' . $pre->getCaption() . '"';
        }

        if (($this->preCaptionBehavior & self::PRE_CAPTION_AS_ARIA_LABEL) > 0) {
            $tag .= ' aria-label="' . $pre->getCaption() . '"';
        }

        return sprintf(
            "<pre%s>\n%s\n</pre>",
            $tag,
            htmlspecialchars($pre->getContents(), ENT_HTML5)
        );
    }
}

A  => src/Encoder/UnsupportedNodeException.php +24 -0
@@ 1,24 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Encoder;

use Ancarda\Gemini\Gemtext\Node\Node;

final class UnsupportedNodeException extends EncoderException
{
    private Node $node;

    public function __construct(Node $node)
    {
        $this->node = $node;

        parent::__construct('Cannot encode node of type ' . get_class($node));
    }

    public function getNode(): Node
    {
        return $this->node;
    }
}

A  => src/Node/Blockquote.php +9 -0
@@ 1,9 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

final class Blockquote extends TextNode
{
}

A  => src/Node/H1.php +12 -0
@@ 1,12 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

/**
 * Heading Level 1
 */
final class H1 extends TextNode
{
}

A  => src/Node/H2.php +12 -0
@@ 1,12 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

/**
 * Heading Level 2
 */
final class H2 extends TextNode
{
}

A  => src/Node/H3.php +12 -0
@@ 1,12 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

/**
 * Heading Level 3
 */
final class H3 extends TextNode
{
}

A  => src/Node/Link.php +30 -0
@@ 1,30 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

/**
 * Hyperlink
 */
final class Link extends Node
{
    private string $link;
    private ?string $label;

    public function __construct(string $link, ?string $label = null)
    {
        $this->link = $link;
        $this->label = $label;
    }

    public function getLink(): string
    {
        return $this->link;
    }

    public function getLabel(): ?string
    {
        return $this->label;
    }
}

A  => src/Node/ListElement.php +9 -0
@@ 1,9 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

final class ListElement extends TextNode
{
}

A  => src/Node/Node.php +14 -0
@@ 1,14 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

/**
 * An object created by parsing Gemtext. This almost always represents a line
 * in a text/gemini file, although in the case of Preformatted, it represents
 * multiple lines, but still a single "object".
 */
abstract class Node
{
}

A  => src/Node/Paragraph.php +9 -0
@@ 1,9 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

final class Paragraph extends TextNode
{
}

A  => src/Node/Preformatted.php +32 -0
@@ 1,32 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

use Ancarda\Gemini\Gemtext\Node;

/**
 * Preformatted textblock with optional caption
 */
final class Preformatted extends Node\Node
{
    private string $contents;
    private ?string $caption;

    public function __construct(string $contents, ?string $caption = null)
    {
        $this->contents = $contents;
        $this->caption = $caption;
    }

    public function getContents(): string
    {
        return $this->contents;
    }

    public function getCaption(): ?string
    {
        return $this->caption;
    }
}

A  => src/Node/TextNode.php +25 -0
@@ 1,25 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Node;

/**
 * A node that just contains text, such as Paragraph or H1. More complex Nodes
 * such as Link and Preformatted will not have a getText method to make it
 * clear which component is which.
 */
abstract class TextNode extends Node
{
    protected string $text;

    public function __construct(string $text)
    {
        $this->text = $text;
    }

    public function getText(): string
    {
        return $this->text;
    }
}

A  => src/Parser.php +57 -0
@@ 1,57 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext;

use Generator;

final class Parser implements ParserInterface
{
    public function parse(iterable $lines): Generator
    {
        $inPreBlock = false;
        $preContents = '';
        $preCaption = null;

        foreach ($lines as $line) {
            if (str_starts_with($line, '```')) {
                if ($inPreBlock) {
                    // This is the end of the pre block, yield everything collected so far.
                    // The last byte of preContents is ignored as it is just a newline character.
                    yield new Node\Preformatted(substr($preContents, 0, -1), $preCaption);
                    $preContents = '';
                } else {
                    // This is the start of the pre block. Extract the caption if there is one.
                    $cap = substr($line, 3);
                    $preCaption = strlen($cap) === 0 ? null : $cap;
                }
                $inPreBlock = !$inPreBlock;
            } elseif ($inPreBlock) {
                $preContents .= $line . "\n";
            } elseif (str_starts_with($line, '# ')) {
                yield new Node\H1(substr($line, 2));
            } elseif (str_starts_with($line, '## ')) {
                yield new Node\H2(substr($line, 3));
            } elseif (str_starts_with($line, '### ')) {
                yield new Node\H3(substr($line, 4));
            } elseif (str_starts_with($line, '>')) {
                yield new Node\Blockquote(substr($line, 1));
            } elseif (str_starts_with($line, '* ')) {
                yield new Node\ListElement(substr($line, 2));
            } elseif (str_starts_with($line, '=>')) {
                // Lop off `=>', then try to extract the label if there is one.
                // Labels are everything after the first space.
                $line = trim(substr($line, 2));
                $space = strpos($line, ' ');
                if ($space === false) {
                    yield new Node\Link($line);
                } else {
                    yield new Node\Link(substr($line, 0, $space), trim(substr($line, $space)));
                }
            } else {
                yield new Node\Paragraph($line);
            }
        }
    }
}

A  => src/ParserInterface.php +16 -0
@@ 1,16 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext;

use Generator;

interface ParserInterface
{
    /**
     * @param iterable<string> $lines
     * @return Generator<Node\Node>
     */
    public function parse(iterable $lines): Generator;
}

A  => src/Util/SimpleTransformer.php +46 -0
@@ 1,46 @@
<?php

declare(strict_types=1);

namespace Ancarda\Gemini\Gemtext\Util;

use Ancarda\Gemini\Gemtext\Encoder\EncoderInterface;
use Ancarda\Gemini\Gemtext\Encoder\HTML;
use Ancarda\Gemini\Gemtext\Parser;
use Ancarda\Gemini\Gemtext\ParserInterface;

/**
 * Simple utility class that makes the primary use-case of parser->encoder easy.
 *
 * This class defaults to Gemini->HTML but is configurable through the setters.
 */
final class SimpleTransformer
{
    private ParserInterface $parser;
    private EncoderInterface $encoder;

    public function __construct()
    {
        $this->parser = new Parser();
        $this->encoder = new HTML();
    }

    public function setParser(ParserInterface $parser): void
    {
        $this->parser = $parser;
    }

    public function setEncoder(EncoderInterface $encoder): void
    {
        $this->encoder = $encoder;
    }

    public function transform(string $gemtext): string
    {
        return implode("\n", iterator_to_array(
            $this->encoder->encode(
                $this->parser->parse(explode("\n", $gemtext))
            )
        ));
    }
}

A  => tests/HtmlEncoderTest.php +186 -0
@@ 1,186 @@
<?php

declare(strict_types=1);

namespace Test;

use Ancarda\Gemini\Gemtext\Encoder\HTML as Encoder;
use Ancarda\Gemini\Gemtext\Encoder\UnsupportedNodeException;
use Ancarda\Gemini\Gemtext\Node\Blockquote;
use Ancarda\Gemini\Gemtext\Node\H1;
use Ancarda\Gemini\Gemtext\Node\H2;
use Ancarda\Gemini\Gemtext\Node\H3;
use Ancarda\Gemini\Gemtext\Node\Link;
use Ancarda\Gemini\Gemtext\Node\ListElement;
use Ancarda\Gemini\Gemtext\Node\Node;
use Ancarda\Gemini\Gemtext\Node\Paragraph;
use Ancarda\Gemini\Gemtext\Node\Preformatted;
use Ancarda\Gemini\Gemtext\Parser;
use ArrayIterator;
use LogicException;
use PHPUnit\Framework\TestCase;

final class HtmlEncoderTest extends TestCase
{
    public function testToHTML(): void
    {
        $encoder = new Encoder();

        self::assertSame(
            [
                '<h1>Introduction to Gemini</h1>',
                '<h2>What is it?</h2>',
                '<p>A new protocol that is</p>',
                '<ul>',
                '<li>Heavier than Gopher</li>',
                '<li>Lighter than the web</li>',
                '</ul>',
                '<h3>Official Website</h3>',
                '<p><a href="gemini://gemini.circumlunar.space/">Gemini Homepage</a></p>',
                '<blockquote>Gemini is really awesome.</blockquote>',
                "<pre>\n&lt;h1&gt;Hello World&lt;/h1&gt;\n</pre>",
            ],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new H1('Introduction to Gemini'),
                new H2('What is it?'),
                new Paragraph('A new protocol that is'),
                new ListElement('Heavier than Gopher'),
                new ListElement('Lighter than the web'),
                new H3('Official Website'),
                new Link('gemini://gemini.circumlunar.space/', 'Gemini Homepage'),
                new Blockquote('Gemini is really awesome.'),
                new Preformatted('<h1>Hello World</h1>'),
            ]))),
        );
    }

    public function testListElementLastInSequenceStillTerminatesUlTag(): void
    {
        $encoder = new Encoder();

        self::assertSame(
            [
                '<ul>',
                '<li>Milk</li>',
                '<li>Eggs</li>',
                '</ul>',
            ],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new ListElement('Milk'),
                new ListElement('Eggs'),
            ]))),
        );
    }

    public function testToHTMLCanOnlyAcceptKnownNodes(): void
    {
        $encoder = new Encoder();
        $bomb = $this->createMock(Node::class);

        try {
            $encoder->encode(new ArrayIterator([$bomb]))->current();
        } catch (UnsupportedNodeException $ex) {
            self::assertSame($bomb, $ex->getNode());
            self::assertSame('Cannot encode node of type ' . get_class($bomb), $ex->getMessage());
            return;
        }

        self::fail('Expected UnsupportedNodeException to be thrown');
    }

    public function testParserCanChangePreCaptionBehavior(): void
    {
        $encoder = new Encoder();

        // By default, pre tags do not have any special handling.
        self::assertSame(
            ["<pre>\n&lt;p&gt;Some HTML&lt;/p&gt;\n</pre>"],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new Preformatted('<p>Some HTML</p>', 'html'),
            ]))),
        );

        // Preformatted text block caption as CSS
        $encoder->setPreCaptionBehavior(Encoder::PRE_CAPTION_AS_CSS);
        self::assertSame(
            ["<pre class=\"html\">\n&lt;p&gt;Some HTML&lt;/p&gt;\n</pre>"],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new Preformatted('<p>Some HTML</p>', 'html'),
            ]))),
        );

        // Preformatted text block caption as aria-label
        $encoder->setPreCaptionBehavior(Encoder::PRE_CAPTION_AS_ARIA_LABEL);
        self::assertSame(
            ["<pre aria-label=\"html\">\n&lt;p&gt;Some HTML&lt;/p&gt;\n</pre>"],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new Preformatted('<p>Some HTML</p>', 'html'),
            ]))),
        );

        // Preformatted text block caption can be both CSS and aria-label
        $encoder->setPreCaptionBehavior(
            Encoder::PRE_CAPTION_AS_CSS | Encoder::PRE_CAPTION_AS_ARIA_LABEL
        );
        self::assertSame(
            ["<pre class=\"html\" aria-label=\"html\">\n&lt;p&gt;Some HTML&lt;/p&gt;\n</pre>"],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new Preformatted('<p>Some HTML</p>', 'html'),
            ]))),
        );

        // Behavior can be set back to normal
        $encoder->reset();
        self::assertSame(
            ["<pre>\n&lt;p&gt;Some HTML&lt;/p&gt;\n</pre>"],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new Preformatted('<p>Some HTML</p>', 'html'),
            ]))),
        );

        // Behavior can also be manually reset
        $encoder->setPreCaptionBehavior(Encoder::PRE_CAPTION_IGNORE);
        self::assertSame(
            ["<pre>\n&lt;p&gt;Some HTML&lt;/p&gt;\n</pre>"],
            iterator_to_array($encoder->encode(new ArrayIterator([
                new Preformatted('<p>Some HTML</p>', 'html'),
            ]))),
        );
    }

    public function testSetPreCaptionBehaviorRejectsInvalidValues(): void
    {
        $encoder = new Encoder();

        $this->expectException(LogicException::class);
        $this->expectExceptionMessage('Invalid behavior code: 123');
        $encoder->setPreCaptionBehavior(123);
    }

    private static function readFile(string $path): string
    {
        $contents = file_get_contents($path);
        if ($contents === false) {
            self::fail('Failed to read file ' . $path);
        }

        return $contents;
    }

    public function testRealWorldFile(): void
    {
        // Large complex real world document
        // From gemini://gemini.circumlunar.space/docs/gemtext.gmi
        $gemtext = explode("\n", self::readFile(__DIR__ . '/gemtext.gmi'));

        $parser = new Parser();
        $encoder = new Encoder();

        $actual = '';
        foreach ($encoder->encode($parser->parse($gemtext)) as $line) {
            $actual .= $line . "\n";
        }

        self::assertEquals(self::readFile(__DIR__ . '/gemtext.html'), $actual);
    }
}

A  => tests/ParserTest.php +128 -0
@@ 1,128 @@
<?php

declare(strict_types=1);

namespace Test;

use Ancarda\Gemini\Gemtext\Node\Blockquote;
use Ancarda\Gemini\Gemtext\Node\H1;
use Ancarda\Gemini\Gemtext\Node\H2;
use Ancarda\Gemini\Gemtext\Node\H3;
use Ancarda\Gemini\Gemtext\Node\Link;
use Ancarda\Gemini\Gemtext\Node\ListElement;
use Ancarda\Gemini\Gemtext\Node\Paragraph;
use Ancarda\Gemini\Gemtext\Parser;
use Ancarda\Gemini\Gemtext\Node\Preformatted;
use PHPUnit\Framework\TestCase;

final class ParserTest extends TestCase
{
    /**
     * @return iterable<string>
     */
    private static function lines(string $text): iterable
    {
        return explode("\n", $text);
    }

    public function testParser(): void
    {
        $parser = new Parser();

        // Text
        self::assertEquals(
            [
                new Paragraph('Line 1'),
                new Paragraph(''),
                new Paragraph('Line 2'),
            ],
            iterator_to_array($parser->parse(self::lines("Line 1\n\nLine 2"))),
        );
        $p = $parser->parse(self::lines('Hello World'))->current();
        self::assertInstanceOf(Paragraph::class, $p);
        self::assertSame('Hello World', $p->getText());

        // Links
        $link = $parser->parse(self::lines('=> gemini://gemini.circumlunar.space/ Gemini Homepage'))->current();
        self::assertInstanceOf(Link::class, $link);
        self::assertSame('gemini://gemini.circumlunar.space/', $link->getLink());
        self::assertSame('Gemini Homepage', $link->getLabel());

        $link = $parser->parse(self::lines('=> gemini://markdain.net'))->current();
        self::assertInstanceOf(Link::class, $link);
        self::assertSame('gemini://markdain.net', $link->getLink());
        self::assertNull($link->getLabel());

        // Whitespace after => is strictly optinal
        $link = $parser->parse(self::lines('=>gemini://nowhitespace.invalid'))->current();
        self::assertInstanceOf(Link::class, $link);
        self::assertSame('gemini://nowhitespace.invalid', $link->getLink());
        self::assertNull($link->getLabel());

        // Headings
        $h1 = $parser->parse(self::lines('# First Level'))->current();
        self::assertInstanceOf(H1::class, $h1);
        self::assertSame('First Level', $h1->getText());

        $h2 = $parser->parse(self::lines('## Second Level'))->current();
        self::assertInstanceOf(H2::class, $h2);
        self::assertSame('Second Level', $h2->getText());

        $h3 = $parser->parse(self::lines('### Third Level'))->current();
        self::assertInstanceOf(H3::class, $h3);
        self::assertSame('Third Level', $h3->getText());

        // Lists
        $li = $parser->parse(self::lines('* List Element'))->current();
        self::assertInstanceOf(ListElement::class, $li);
        self::assertSame('List Element', $li->getText());
        self::assertEquals(
            [new ListElement('Milk'), new ListElement('Cheese')],
            iterator_to_array($parser->parse(self::lines("* Milk\n* Cheese"))),
        );

        // Blockquotes
        $bq = $parser->parse(self::lines('>Anything worth doing is worth doing well'))->current();
        self::assertInstanceOf(Blockquote::class, $bq);
        self::assertSame('Anything worth doing is worth doing well', $bq->getText());

        // Preformatted Text
        $pre = $parser->parse(self::lines("```html\n<h1>Hello World</h1>\n```"))->current();
        self::assertInstanceOf(Preformatted::class, $pre);
        self::assertSame('html', $pre->getCaption());
        self::assertSame('<h1>Hello World</h1>', $pre->getContents());
    }

    public function testParserCanHandleGemtextInsidePre(): void
    {
        $parser = new Parser();

        self::assertEquals(
            [new Preformatted('=> gemini://nowhere')],
            iterator_to_array($parser->parse(self::lines("```\n=> gemini://nowhere\n```")))
        );
    }

    public function testPreTagsDoNotCrossContaminate(): void
    {
        $parser = new Parser();

        self::assertEquals(
            [
                new Preformatted('1'),
                new Paragraph('p'),
                new Preformatted('2'),
            ],
            iterator_to_array($parser->parse(self::lines(<<<EOF
```
1
```
p
```
2
```
EOF
            )))
        );
    }
}

A  => tests/UtilTest.php +54 -0
@@ 1,54 @@
<?php