From 9cb6006b69c4decf129a323b3c7a022a3241c77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zdene=CC=8Ck=20Drahos=CC=8C?= Date: Sun, 27 Jun 2021 10:00:43 +0200 Subject: [PATCH] Refactoring including assets --- Render/Html/GetNelmioAsset.php | 78 ++++++++++++--- Render/Html/HtmlOpenApiRenderer.php | 24 ++--- Resources/config/services.xml | 3 + Resources/views/SwaggerUi/index.html.twig | 28 +----- Tests/Render/Html/GetNelmioAssetTest.php | 112 ++++++++++++++++++++++ 5 files changed, 192 insertions(+), 53 deletions(-) create mode 100644 Tests/Render/Html/GetNelmioAssetTest.php diff --git a/Render/Html/GetNelmioAsset.php b/Render/Html/GetNelmioAsset.php index 8767682..38e85a6 100644 --- a/Render/Html/GetNelmioAsset.php +++ b/Render/Html/GetNelmioAsset.php @@ -12,30 +12,82 @@ namespace Nelmio\ApiDocBundle\Render\Html; use Symfony\Bridge\Twig\Extension\AssetExtension; +use Twig\TwigFunction; class GetNelmioAsset { private $assetExtension; - private $defaultAssetsMode; + private $resourcesDir; + private $cdnUrl; + private $assetsMode = AssetsMode::BUNDLE; - public function __construct(AssetExtension $assetExtension, $defaultAssetsMode) + public function __construct(AssetExtension $assetExtension) { $this->assetExtension = $assetExtension; - $this->defaultAssetsMode = $defaultAssetsMode; + $this->cdnUrl = 'https://cdn.jsdelivr.net/gh/nelmio/NelmioApiDocBundle/Resources/public'; + $this->resourcesDir = __DIR__.'/../../Resources/public'; } - public function __invoke($asset, $forcedMode = null) + public function toTwigFunction($assetsMode): TwigFunction { - $mode = $forcedMode ?: $this->defaultAssetsMode; - if (AssetsMode::CDN === $mode) { - return sprintf( - 'https://cdn.jsdelivr.net/gh/nelmio/NelmioApiDocBundle@4.1/Resources/public/%s', - $asset - ); - } elseif (AssetsMode::OFFLINE === $mode) { - return file_get_contents(__DIR__.sprintf('/../../Resources/public/%s', $asset)); + $this->assetsMode = $assetsMode; + + return new TwigFunction('nelmioAsset', $this, ['is_safe' => ['html']]); + } + + public function __invoke($asset) + { + [$extension, $mode] = $this->getExtension($asset); + [$resource, $isInline] = $this->getResource($asset, $mode); + if ('js' == $extension) { + return $this->renderJavascript($resource, $isInline); + } elseif ('css' == $extension) { + return $this->renderCss($resource, $isInline); } else { - return $this->assetExtension->getAssetUrl(sprintf('bundles/nelmioapidoc/%s', $asset)); + return $resource; + } + } + + private function getExtension($asset) + { + $extension = mb_substr($asset, -3, 3, 'utf-8'); + if ('.js' === $extension) { + return ['js', $this->assetsMode]; + } elseif ('png' === $extension) { + return ['png', AssetsMode::OFFLINE == $this->assetsMode ? AssetsMode::CDN : $this->assetsMode]; + } else { + return ['css', $this->assetsMode]; + } + } + + private function getResource($asset, $mode) + { + if (filter_var($asset, FILTER_VALIDATE_URL)) { + return [$asset, false]; + } elseif (AssetsMode::OFFLINE === $mode) { + return [file_get_contents($this->resourcesDir.'/'.$asset), true]; + } elseif (AssetsMode::CDN === $mode) { + return [$this->cdnUrl.'/'.$asset, false]; + } else { + return [$this->assetExtension->getAssetUrl(sprintf('bundles/nelmioapidoc/%s', $asset)), false]; + } + } + + private function renderJavascript(string $script, bool $isInline) + { + if ($isInline) { + return sprintf('', $script); + } else { + return sprintf('', $script); + } + } + + private function renderCss(string $stylesheet, bool $isInline) + { + if ($isInline) { + return sprintf('', $stylesheet); + } else { + return sprintf('', $stylesheet); } } } diff --git a/Render/Html/HtmlOpenApiRenderer.php b/Render/Html/HtmlOpenApiRenderer.php index 5bb8645..bedf14e 100644 --- a/Render/Html/HtmlOpenApiRenderer.php +++ b/Render/Html/HtmlOpenApiRenderer.php @@ -16,28 +16,23 @@ use Nelmio\ApiDocBundle\Render\OpenApiRenderer; use Nelmio\ApiDocBundle\Render\RenderOpenApi; use OpenApi\Annotations\OpenApi; use OpenApi\Annotations\Server; -use Symfony\Bridge\Twig\Extension\AssetExtension; use Twig\Environment; -use Twig\TwigFunction; class HtmlOpenApiRenderer implements OpenApiRenderer { - /** - * @var Environment|\Twig_Environment - */ + /** @var Environment|\Twig_Environment */ private $twig; - /** - * @var AssetExtension - */ - private $assetExtension; - public function __construct($twig, AssetExtension $assetExtension) + /** @var GetNelmioAsset */ + private $getNelmioAsset; + + public function __construct($twig, GetNelmioAsset $getNelmioAsset) { if (!$twig instanceof \Twig_Environment && !$twig instanceof Environment) { throw new InvalidArgumentException(sprintf('Providing an instance of "%s" as twig is not supported.', get_class($twig))); } $this->twig = $twig; - $this->assetExtension = $assetExtension; + $this->getNelmioAsset = $getNelmioAsset; } public function getFormat(): string @@ -53,12 +48,7 @@ class HtmlOpenApiRenderer implements OpenApiRenderer 'swagger_ui_config' => [], ]; - $this->twig->addFunction( - new TwigFunction( - 'nelmioAsset', - new GetNelmioAsset($this->assetExtension, $options['assets_mode']) - ) - ); + $this->twig->addFunction($this->getNelmioAsset->toTwigFunction($options['assets_mode'])); return $this->twig->render( '@NelmioApiDoc/SwaggerUi/index.html.twig', diff --git a/Resources/config/services.xml b/Resources/config/services.xml index e0127ae..d125a10 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -33,6 +33,9 @@ + + + diff --git a/Resources/views/SwaggerUi/index.html.twig b/Resources/views/SwaggerUi/index.html.twig index 0db7f8b..a1b3129 100644 --- a/Resources/views/SwaggerUi/index.html.twig +++ b/Resources/views/SwaggerUi/index.html.twig @@ -14,13 +14,8 @@ file that was distributed with this source code. #} {% block title %}{{ swagger_data.spec.info.title }}{% endblock title %} {% block stylesheets %} - {% if assets_mode == 'offline' %} - - - {% else %} - - - {% endif %} + {{ nelmioAsset('swagger-ui/swagger-ui.css') }} + {{ nelmioAsset('style.css') }} {% endblock stylesheets %} {% block swagger_data %} @@ -59,11 +54,7 @@ file that was distributed with this source code. #}
{% block header %} {% endblock header %}
@@ -73,20 +64,11 @@ file that was distributed with this source code. #} {% endblock %} {% block javascripts %} - {% if assets_mode == 'offline' %} - - - {% else %} - - - {% endif %} + {{ nelmioAsset('swagger-ui/swagger-ui-bundle.js') }} + {{ nelmioAsset('swagger-ui/swagger-ui-standalone-preset.js') }} {% endblock javascripts %} - {% if assets_mode == 'offline' %} - - {% else %} - - {% endif %} + {{ nelmioAsset('init-swagger-ui.js') }} {% block swagger_initialization %} ', + ], + 'cdn js' => [ + AssetsMode::CDN, + 'init-swagger-ui.js', + '', + ], + 'offline js' => [ + AssetsMode::OFFLINE, + 'init-swagger-ui.js', + '', + ], + 'external js' => [ + AssetsMode::BUNDLE, + 'https://cdn.com/my.js', + '', + ], + ]; + } + + private function provideImage($cdnDir) + { + return [ + 'bundled image' => [ + AssetsMode::BUNDLE, + 'logo.png', + '/bundles/nelmioapidoc/logo.png', + ], + 'cdn image' => [ + AssetsMode::CDN, + 'logo.png', + $cdnDir.'/logo.png', + ], + 'offline image fallbacks to cdn' => [ + AssetsMode::OFFLINE, + 'logo.png', + $cdnDir.'/logo.png', + ], + ]; + } +}