diff --git a/Dockerfile b/Dockerfile index 795f36f8..c81b9500 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,6 +39,7 @@ RUN \ php8.1-mbstring \ php8.1-xml \ php8.1-curl \ + php8.1-gd \ nodejs \ openjdk-18-jre \ xfonts-75dpi \ @@ -123,6 +124,16 @@ RUN \ --mount=type=cache,target=/root/.composer,id=composer \ composer install +FROM development AS test-output-builder + +COPY --link ./test/fixture/templates /docs-src/templates +COPY --link ./test/fixture/docbook /docs-src/book +COPY --link ./test/fixture/feature /docs-src/features +RUN bin/docbook-tool --html --pdf + +FROM scratch AS test-output + +COPY --from=test-output-builder /docs-package / FROM development AS tested diff --git a/Makefile b/Makefile index 6f96a068..434e4c47 100644 --- a/Makefile +++ b/Makefile @@ -21,5 +21,10 @@ cs: build ## Run coding standards checks static-analysis: build ## Run the static analysis checks docker run --rm --entrypoint=php ghcr.io/roave/docbooktool:test-image vendor/bin/psalm +test-output: ## Write the test fixture outputs to build/ directory - useful for manual visual inspection + rm -Rf build + mkdir -p build + docker buildx build --output=build --target=test-output --tag=ghcr.io/roave/docbooktool:test-image . + production: ## Build and tag a production image docker buildx build --load --target=production --tag=ghcr.io/roave/docbooktool:latest . diff --git a/bin/docbook-tool.php b/bin/docbook-tool.php index 493020e4..e942d085 100644 --- a/bin/docbook-tool.php +++ b/bin/docbook-tool.php @@ -11,6 +11,7 @@ use Monolog\Logger; use Roave\DocbookTool\Formatter\AggregatePageFormatter; use Roave\DocbookTool\Formatter\ExtractFrontMatter; +use Roave\DocbookTool\Formatter\InlineExternalImages; use Roave\DocbookTool\Formatter\InlineFeatureFile; use Roave\DocbookTool\Formatter\MarkdownToHtml; use Roave\DocbookTool\Formatter\RenderPlantUmlDiagramInline; @@ -40,6 +41,7 @@ $pageFormatters = [ new ExtractFrontMatter(), + new InlineExternalImages($contentPath), new RenderPlantUmlDiagramInline(), new MarkdownToHtml(), ]; diff --git a/composer.json b/composer.json index 137a876e..8add405f 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ ], "require": { "php": "~8.1.3", + "ext-gd": "*", "guzzlehttp/guzzle": "^7.5", "guzzlehttp/psr7": "^2.4", "jasny/twig-extensions": "^1.3", diff --git a/composer.lock b/composer.lock index 5d9ad403..fb7f9f96 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e4a7c8eb6435cba8ee82b12ce1869402", + "content-hash": "97217b6656b41dc2a50cc091cb94de84", "packages": [ { "name": "guzzlehttp/guzzle", @@ -3255,19 +3255,21 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "86b842d48cdaaab1bf3dc24fdc830bf7b58cfcab" + "reference": "7756fea7a811a23d92009e03fdad3b91352f9b4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/86b842d48cdaaab1bf3dc24fdc830bf7b58cfcab", - "reference": "86b842d48cdaaab1bf3dc24fdc830bf7b58cfcab", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/7756fea7a811a23d92009e03fdad3b91352f9b4f", + "reference": "7756fea7a811a23d92009e03fdad3b91352f9b4f", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", + "admidio/admidio": "<4.1.9", "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", + "aheinze/cockpit": "<=2.2.1", "akaunting/akaunting": "<2.1.13", - "alextselegidis/easyappointments": "<1.4.3", + "alextselegidis/easyappointments": "<=1.4.3", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", "amazing/media2click": ">=1,<1.3.3", "amphp/artax": "<1.0.6|>=2,<2.0.6", @@ -3283,18 +3285,23 @@ "bagisto/bagisto": "<0.1.5", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", + "barryvdh/laravel-translation-manager": "<0.6.2", "baserproject/basercms": "<4.5.4", "billz/raspap-webgui": "<=2.6.6", "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "bmarshall511/wordpress_zero_spam": "<5.2.13", "bolt/bolt": "<3.7.2", - "bolt/core": "<4.1.13", + "bolt/core": "<=4.2", "bottelet/flarepoint": "<2.2.1", "brightlocal/phpwhois": "<=4.2.5", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", "buddypress/buddypress": "<7.2.1", "bugsnag/bugsnag-laravel": ">=2,<2.0.2", "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", - "cakephp/cakephp": "<4.0.6", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.6", "cardgate/magento2": "<2.0.33", "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", "cartalyst/sentry": "<=2.1.6", @@ -3304,16 +3311,22 @@ "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<=3.0.6", "codeigniter4/framework": "<4.1.9", + "codeigniter4/shield": "= 1.0.0-beta", "codiad/codiad": "<=2.8.4", - "composer/composer": "<1.10.23|>=2-alpha.1,<2.1.9", + "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", "concrete5/concrete5": "<9", - "concrete5/core": "<8.5.7", + "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|= 4.10.0", + "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", - "craftcms/cms": "<3.7.14", + "contao/managed-edition": "<=1.5", + "craftcms/cms": ">= 4.0.0-RC1, < 4.2.1|<4.2.1", "croogo/croogo": "<3.0.7", + "cuyz/valinor": "<0.12", + "czproject/git-php": "<4.0.3", + "darylldoyle/safe-svg": "<1.9.10", "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", @@ -3327,57 +3340,67 @@ "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<16|>= 3.3.beta1, < 13.0.2", - "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=7,<7.88|>=8,<9.2.13|>=9.3,<9.3.6", + "dolibarr/dolibarr": "<16|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dompdf/dompdf": "<2", + "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", "dweeves/magmi": "<=0.7.24", "ecodev/newsletter": "<=4", "ectouch/ectouch": "<=2.7.2", + "elefant/cms": "<1.3.13", "elgg/elgg": "<3.3.24|>=4,<4.0.5", "endroid/qr-code-bundle": "<3.4.2", "enshrined/svg-sanitize": "<0.15", "erusev/parsedown": "<1.7.2", "ether/logs": "<3.0.4", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "= 3.0.0|<2.2.3", "ezsystems/demobundle": ">=5.4,<5.4.6.1", "ezsystems/ez-support-tools": ">=2.2,<2.2.3", "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<=1.5.25", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.27", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", - "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.12", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.19", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.26", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.29", "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", "ezsystems/repository-forms": ">=2.3,<2.3.2.1", "ezyang/htmlpurifier": "<4.1.1", "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<=2022.8", "feehi/cms": "<=2.1.1", "feehi/feehicms": "<=0.1.3", + "fenom/fenom": "<=2.12.1", + "filegator/filegator": "<7.8", "firebase/php-jwt": "<2", "flarum/core": ">=1,<=1.0.1", "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", "flarum/tags": "<=0.1-beta.13", "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3-beta.2,<1.1.7", + "fof/upload": "<1.2.3", "fooman/tcpdf": "<6.2.22", - "forkcms/forkcms": "<=5.9.2", + "forkcms/forkcms": "<5.11.1", "fossar/tcpdf-parser": "<6.2.22", - "francoisjacquet/rosariosis": "<8.1.1", + "francoisjacquet/rosariosis": "<10.1", "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "froala/wysiwyg-editor": "<3.2.7", + "froxlor/froxlor": "<0.10.38", "fuel/core": "<1.8.1", "gaoming13/wechat-php-sdk": "<=1.10.2", "genix/cms": "<=1.1.11", - "getgrav/grav": "<1.7.31", - "getkirby/cms": "<3.5.8", + "getgrav/grav": "<1.7.34", + "getkirby/cms": "<3.5.8.1|>=3.6,<3.6.6.1|>=3.7,<3.7.4", "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", "gilacms/gila": "<=1.11.4", "globalpayments/php-sdk": "<2", "google/protobuf": "<3.15", @@ -3385,25 +3408,34 @@ "gree/jose": "<=2.2", "gregwar/rst": "<1.0.3", "grumpydictator/firefly-iii": "<5.6.5", - "guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1", - "helloxz/imgurl": "<=2.31", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/psr7": "<1.8.4|>=2,<2.1.1", + "helloxz/imgurl": "= 2.31|<=2.31", "hillelcoren/invoice-ninja": "<5.3.35", "hjue/justwriting": "<=1", "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4", "ibexa/post-install": "<=1.0.4", "icecoder/icecoder": "<=8.1", + "idno/known": "<=1.3.1", "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", - "impresscms/impresscms": "<=1.4.2", + "impresscms/impresscms": "<=1.4.3", "in2code/femanager": "<5.5.1|>=6,<6.3.1", + "in2code/lux": "<17.6.1|>=18,<24.0.2", "intelliants/subrion": "<=4.2.1", + "islandora/islandora": ">=2,<2.4.1", "ivankristianto/phpwhois": "<=4.3", "jackalope/jackalope-doctrine-dbal": "<1.7.4", "james-heinrich/getid3": "<1.9.21", - "joomla/archive": "<1.1.10", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<1.4.4|>=2,<2.0.1", + "joomla/input": ">=2,<2.0.2", "joomla/session": "<1.3.1", "jsdecena/laracom": "<2.0.9", "jsmitty12/phpwhois": "<5.1", @@ -3411,8 +3443,10 @@ "kevinpapst/kimai2": "<1.16.7", "kitodo/presentation": "<3.1.2", "klaviyo/magento2-extension": ">=1,<3", + "krayin/laravel-crm": "<1.2.2", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-diactoros": "<2.11.1", "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", "laminas/laminas-http": "<2.14.2", "laravel/fortify": "<1.11.1", @@ -3424,53 +3458,62 @@ "league/commonmark": "<0.18.3", "league/flysystem": "<1.1.4|>=2,<2.1.1", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", - "librenms/librenms": "<22.2.2", + "librenms/librenms": "<=22.8", "limesurvey/limesurvey": "<3.27.19", "livehelperchat/livehelperchat": "<=3.91", "livewire/livewire": ">2.2.4,<2.2.6", "lms/routes": "<2.1.1", "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "luyadev/yii-helpers": "<1.2.1", "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3", "magento/magento1ce": "<1.9.4.3", "magento/magento1ee": ">=1,<1.14.4.3", "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", "marcwillmann/turn": "<0.3.3", - "matyhtf/framework": "<=3.0.5", - "mautic/core": "<4.2|= 2.13.1", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<4.3|= 2.13.1", "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", - "microweber/microweber": "<1.3", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "microweber/microweber": "<=1.3.1", "miniorange/miniorange-saml": "<1.4.3", "mittwald/typo3_forum": "<1.2.1", "modx/revolution": "<= 2.8.3-pl|<2.8", + "mojo42/jirafeau": "<4.4", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<3.9.11|>=3.10-beta,<3.10.8|>=3.11,<3.11.5", + "moodle/moodle": "<4.0.1", "mustache/mustache": ">=2,<2.14.1", "namshi/jose": "<2.2", "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.4", "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", - "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", "nilsteampassnet/teampass": "<=2.1.27.36", - "nukeviet/nukeviet": "<4.3.4", - "nystudio107/craft-seomatic": "<3.3", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "nukeviet/nukeviet": "<4.5.2", + "nystudio107/craft-seomatic": "<3.4.12", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", "october/backend": "<1.1.2", "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12", "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<1.0.475|>=1.1,<1.1.11|>=2,<2.1.27", + "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.15", "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.7.4", "opencart/opencart": "<=3.0.3.2", "openid/php-openid": "<2.3", "openmage/magento-lts": "<19.4.15|>=20,<20.0.13", "orchid/platform": ">=9,<9.4.4", + "oro/commerce": ">=5,<5.0.4", "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8", + "packbackbooks/lti-1-3-php-library": "<5", "padraic/humbug_get_contents": "<1.1.2", "pagarme/pagarme-php": ">=0,<3", "pagekit/pagekit": "<=1.0.18", @@ -3485,26 +3528,29 @@ "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<4.9.8|>=5,<5.0.3|>=5.1,<5.1.2", - "phpoffice/phpexcel": "<1.8.2", + "phpmyadmin/phpmyadmin": "<5.1.3", + "phpoffice/phpexcel": "<1.8", "phpoffice/phpspreadsheet": "<1.16", "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", "phpservermon/phpservermon": "<=3.5.2", - "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", - "pimcore/pimcore": "<=10.3.2", - "pocketmine/pocketmine-mp": "<4.0.7", + "pimcore/data-hub": "<1.2.4", + "pimcore/pimcore": "<10.5.6", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "<4.7.2|>= 4.0.0-BETA5, < 4.4.2", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/blockwishlist": ">=2,<2.1.1", "prestashop/contactform": ">1.0.1,<4.3", "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": ">=1.7,<=1.7.8.2", - "prestashop/productcomments": ">=4,<4.2.1", + "prestashop/prestashop": ">=1.6.0.10,<1.7.8.7", + "prestashop/productcomments": "<5.0.2", "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", "prestashop/ps_linklist": "<3.1", - "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2", + "privatebin/privatebin": "<1.4", "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", "pterodactyl/panel": "<1.7", @@ -3512,31 +3558,37 @@ "pusher/pusher-php-server": "<2.2.1", "pwweb/laravel-core": "<=0.3.6-beta", "rainlab/debugbar-plugin": "<3.1", - "remdex/livehelperchat": "<3.93", + "rankmath/seo-by-rank-math": "<=1.0.95", + "react/http": ">=0.7,<1.7", + "remdex/livehelperchat": "<3.99", "rmccue/requests": ">=1.6,<1.8", "robrichards/xmlseclibs": "<3.0.4", "rudloff/alltube": "<3.0.3", - "s-cart/s-cart": "<6.7.2", + "s-cart/core": "<6.9", + "s-cart/s-cart": "<6.9", "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", "serluck/phpwhois": "<=4.2.6", - "shopware/core": "<=6.4.8.1", - "shopware/platform": "<=6.4.8.1", + "shopware/core": "<=6.4.9", + "shopware/platform": "<=6.4.9", "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<5.7.7", + "shopware/shopware": "<=5.7.14", "shopware/storefront": "<=6.4.8.1", - "showdoc/showdoc": "<=2.10.2", + "shopxo/shopxo": "<2.2.6", + "showdoc/showdoc": "<2.10.4", "silverstripe/admin": ">=1,<1.8.1", - "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2", + "silverstripe/assets": ">=1,<1.10.1", "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<4.10.1", + "silverstripe/framework": "<4.10.9", "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", "silverstripe/subsites": ">=2,<2.1.1", "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", "silverstripe/userforms": "<3", @@ -3546,14 +3598,15 @@ "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", "simplito/elliptic-php": "<1.0.6", "slim/slim": "<2.6", - "smarty/smarty": "<3.1.43|>=4,<4.0.3", - "snipe/snipe-it": "<5.3.11", + "smarty/smarty": "<3.1.47|>=4,<4.2.1", + "snipe/snipe-it": "<6.0.11|>= 6.0.0-RC-1, <= 6.0.0-RC-5", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", "spipu/html2pdf": "<5.2.4", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "ssddanbrown/bookstack": "<22.2.3", + "statamic/cms": "<3.2.39|>=3.3,<3.3.2", "stormpath/sdk": ">=0,<9.9.99", "studio-42/elfinder": "<2.1.59", "subrion/cms": "<=4.2.1", @@ -3561,10 +3614,10 @@ "swiftmailer/swiftmailer": ">=4,<5.4.5", "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", - "sylius/grid-bundle": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", - "sylius/sylius": "<1.6.9|>=1.7,<1.7.9|>=1.8,<1.8.3|>=1.9,<1.9.5", + "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2", "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", "symbiote/silverstripe-versionedfiles": "<=2.0.3", @@ -3599,43 +3652,52 @@ "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", + "tastyigniter/tastyigniter": "<3.3", "tecnickcom/tcpdf": "<6.2.22", "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<=5.1.7", "tinymce/tinymce": "<5.10", "titon/framework": ">=0,<9.9.99", - "topthink/framework": "<6.0.9", + "topthink/framework": "<=6.0.13", "topthink/think": "<=6.0.9", "topthink/thinkphp": "<=3.2.3", "tribalsystems/zenario": "<9.2.55826", "truckersmp/phpwhois": "<=4.3.1", "twig/twig": "<1.38|>=2,<2.14.11|>=3,<3.3.8", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.32|>=11,<11.5.16", "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", - "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<=7.6.52|>=8,<=8.7.41|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5", + "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<7.6.58|>=8,<8.7.48|>=9,<9.5.37|>=10,<10.4.32|>=11,<11.5.16", "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<1.0.7|>=2,<2.0.16", "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", "ua-parser/uap-php": "<3.8", - "unisharp/laravel-filemanager": "<=2.3", + "unisharp/laravel-filemanager": "<=2.5.1", "userfrosting/userfrosting": ">=0.3.1,<4.6.3", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", "vanilla/safecurl": "<0.9.2", "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", - "vrana/adminer": "<4.7.9", + "vrana/adminer": "<4.8.1", "wallabag/tcpdf": "<6.2.22", "wanglelecc/laracms": "<=1.0.3", "web-auth/webauthn-framework": ">=3.3,<3.3.4", "webcoast/deferred-image-processing": "<1.0.2", "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", + "wintercms/winter": "<1.0.475|>=1.1,<1.1.9", + "woocommerce/woocommerce": "<6.6", "wp-cli/wp-cli": "<2.5", - "yetiforce/yetiforce-crm": "<=6.3", + "wp-graphql/wp-graphql": "<0.3.5", + "wpanel/wpanel4-cms": "<=4.3.1", + "wwbn/avideo": "<=11.6", + "yeswiki/yeswiki": "<4.1", + "yetiforce/yetiforce-crm": "<=6.4", "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", "yiisoft/yii": ">=1.1.14,<1.1.15", @@ -3654,10 +3716,10 @@ "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", - "zendframework/zend-diactoros": ">=1,<1.8.4", - "zendframework/zend-feed": ">=1,<2.10.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-http": ">=1,<2.8.1", + "zendframework/zend-http": "<2.8.1", "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", @@ -3709,7 +3771,7 @@ "type": "tidelift" } ], - "time": "2022-03-14T19:04:00+00:00" + "time": "2022-09-21T22:04:29+00:00" }, { "name": "sebastian/cli-parser", @@ -5523,8 +5585,9 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~8.1.3" + "php": "~8.1.3", + "ext-gd": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 510ddb1d..76c63bee 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -6,6 +6,7 @@ bin src + test/unit test/integration diff --git a/psalm.xml.dist b/psalm.xml.dist index 45260c76..96ed3470 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -8,6 +8,7 @@ + diff --git a/src/Formatter/InlineExternalImages.php b/src/Formatter/InlineExternalImages.php new file mode 100644 index 00000000..c7c14e64 --- /dev/null +++ b/src/Formatter/InlineExternalImages.php @@ -0,0 +1,57 @@ +withReplacedContent( + preg_replace_callback( + '/!\[([^]]+)]\(([^)]*?)\)/', + function (array $m) { + /** @var array{1: string, 2: string} $m */ + $altText = $m[1]; + $imagePath = $m[2]; + + $fullImagePath = $this->docbookPath . '/' . $imagePath; + + $imageContent = file_get_contents($fullImagePath); + + $imageInfo = getimagesize($fullImagePath); + + if (! is_array($imageInfo) || ! array_key_exists('mime', $imageInfo) || ! is_string($imageInfo['mime'])) { + throw new RuntimeException('Unable to determine mime type of ' . $fullImagePath); + } + + return sprintf( + '![%s](data:%s;base64,%s)', + $altText, + $imageInfo['mime'], + base64_encode($imageContent), + ); + }, + $page->content(), + ), + ); + } +} diff --git a/test/fixture/docbook/smile.gif b/test/fixture/docbook/smile.gif new file mode 100644 index 00000000..9b787db3 Binary files /dev/null and b/test/fixture/docbook/smile.gif differ diff --git a/test/fixture/docbook/smile.jpg b/test/fixture/docbook/smile.jpg new file mode 100644 index 00000000..6181f905 Binary files /dev/null and b/test/fixture/docbook/smile.jpg differ diff --git a/test/fixture/docbook/smile.png b/test/fixture/docbook/smile.png new file mode 100644 index 00000000..d4c763fd Binary files /dev/null and b/test/fixture/docbook/smile.png differ diff --git a/test/fixture/docbook/test.md b/test/fixture/docbook/test.md index 5b4586bd..c49e4590 100644 --- a/test/fixture/docbook/test.md +++ b/test/fixture/docbook/test.md @@ -36,3 +36,13 @@ Bob->Alice : hello hexagon TestingHexagon @enduml ``` + +## Some images + +Here are some images: + +![A smiley face in PNG](./smile.png) +![A smiley face in JPG](./smile.jpg) +![A smiley face in GIF](./smile.gif) + +They are hand drawn, that's why they look rubbish. diff --git a/test/fixture/expectations/out.html b/test/fixture/expectations/out.html index d5dbbf47..28f17872 100644 --- a/test/fixture/expectations/out.html +++ b/test/fixture/expectations/out.html @@ -51,6 +51,16 @@

A diagram

Diagram

+

Some images

+ +

Here are some images:

+ +

A smiley face in PNG +A smiley face in JPG +A smiley face in GIF

+ +

They are hand drawn, that's why they look rubbish.

+
diff --git a/test/integration/DocbookToolGeneratorTest.php b/test/integration/DocbookToolGeneratorTest.php index 2e81269b..82b45f4d 100644 --- a/test/integration/DocbookToolGeneratorTest.php +++ b/test/integration/DocbookToolGeneratorTest.php @@ -8,6 +8,7 @@ use Psr\Log\NullLogger; use Roave\DocbookTool\Formatter\AggregatePageFormatter; use Roave\DocbookTool\Formatter\ExtractFrontMatter; +use Roave\DocbookTool\Formatter\InlineExternalImages; use Roave\DocbookTool\Formatter\InlineFeatureFile; use Roave\DocbookTool\Formatter\MarkdownToHtml; use Roave\DocbookTool\Formatter\RenderPlantUmlDiagramInline; @@ -47,6 +48,7 @@ public function testGeneration(): void [ new AggregatePageFormatter([ new ExtractFrontMatter(), + new InlineExternalImages(self::CONTENT_PATH), new RenderPlantUmlDiagramInline(), new MarkdownToHtml(), new InlineFeatureFile(self::FEATURES_PATH), diff --git a/test/unit/Formatter/ExtractFrontMatterTest.php b/test/unit/Formatter/ExtractFrontMatterTest.php index 0fcef26c..d455ae8f 100644 --- a/test/unit/Formatter/ExtractFrontMatterTest.php +++ b/test/unit/Formatter/ExtractFrontMatterTest.php @@ -4,15 +4,16 @@ namespace Roave\DocbookToolUnitTest\Formatter; +use PHPUnit\Framework\TestCase; use Roave\DocbookTool\DocbookPage; use Roave\DocbookTool\Formatter\AggregatePageFormatter; use Roave\DocbookTool\Formatter\ExtractFrontMatter; -use PHPUnit\Framework\TestCase; use Roave\DocbookTool\Formatter\MarkdownToHtml; /** @covers \Roave\DocbookTool\Formatter\ExtractFrontMatter */ final class ExtractFrontMatterTest extends TestCase { + /** @return array */ public function titleProvider(): array { return [ @@ -70,7 +71,12 @@ public function titleProvider(): array ]; } - /** @dataProvider titleProvider */ + /** + * @param non-empty-string $content + * @param non-empty-string $expectedTitle + * + * @dataProvider titleProvider + */ public function testTitleCanBeSetInFrontMatter(string $content, string $expectedTitle): void { self::assertSame( @@ -78,7 +84,7 @@ public function testTitleCanBeSetInFrontMatter(string $content, string $expected (new AggregatePageFormatter([ new ExtractFrontMatter(), new MarkdownToHtml(), - ]))(DocbookPage::fromSlugAndContent('slug', $content))->title() + ]))(DocbookPage::fromSlugAndContent('slug', $content))->title(), ); } } diff --git a/test/unit/Formatter/InlineExternalImagesTest.php b/test/unit/Formatter/InlineExternalImagesTest.php new file mode 100644 index 00000000..be005db1 --- /dev/null +++ b/test/unit/Formatter/InlineExternalImagesTest.php @@ -0,0 +1,107 @@ + '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', + self::MIME_PNG => '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', + self::MIME_GIF => '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', + ]; + + /** @return list */ + public function contentAndImagePathProvider(): array + { + return [ + [__DIR__ . '/../../fixture/docbook', 'smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture/docbook', './smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture/docbook/', 'smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture/docbook/', './smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture', './docbook/smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture', 'docbook/smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture/', './docbook/smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture/', 'docbook/smile.jpg', self::MIME_JPG], + [__DIR__ . '/../../fixture/docbook', 'smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture/docbook', './smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture/docbook/', 'smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture/docbook/', './smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture', './docbook/smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture', 'docbook/smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture/', './docbook/smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture/', 'docbook/smile.png', self::MIME_PNG], + [__DIR__ . '/../../fixture/docbook', 'smile.gif', self::MIME_GIF], + [__DIR__ . '/../../fixture/docbook', './smile.gif', self::MIME_GIF], + [__DIR__ . '/../../fixture/docbook/', 'smile.gif', self::MIME_GIF], + [__DIR__ . '/../../fixture/docbook/', './smile.gif', self::MIME_GIF], + [__DIR__ . '/../../fixture', './docbook/smile.gif', self::MIME_GIF], + [__DIR__ . '/../../fixture', 'docbook/smile.gif', self::MIME_GIF], + [__DIR__ . '/../../fixture/', './docbook/smile.gif', self::MIME_GIF], + [__DIR__ . '/../../fixture/', 'docbook/smile.gif', self::MIME_GIF], + ]; + } + + /** + * @param non-empty-string $contentPath + * @param non-empty-string $imagePath + * @param non-empty-string $expectedMimeType + * + * @dataProvider contentAndImagePathProvider + */ + public function testExternalImagesAreInlined(string $contentPath, string $imagePath, string $expectedMimeType): void + { + $markdown = <<content()); + } + + public function testImageNotExisting(): void + { + $this->expectError(); + $this->expectErrorMessage('Failed to open stream: No such file or directory'); + (new InlineExternalImages(__DIR__ . '/../../fixture/docbook'))( + DocbookPage::fromSlugAndContent('slug', '![the alt text](something-that-should-not-exist.jpg)'), + ); + } + + public function testImageMimeTypeNotDetected(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Unable to determine mime type'); + (new InlineExternalImages(__DIR__ . '/../../fixture/docbook'))( + DocbookPage::fromSlugAndContent('slug', '![the alt text](test.md)'), + ); + } +}