diff --git a/Command/DumpCommand.php b/Command/DumpCommand.php
index b2438da..481c682 100644
--- a/Command/DumpCommand.php
+++ b/Command/DumpCommand.php
@@ -11,6 +11,7 @@
namespace Nelmio\ApiDocBundle\Command;
+use Nelmio\ApiDocBundle\Render\Html\AssetsMode;
use Nelmio\ApiDocBundle\Render\RenderOpenApi;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
@@ -24,6 +25,15 @@ class DumpCommand extends Command
*/
private $renderOpenApi;
+ /**
+ * @var mixed[]
+ */
+ private $defaultHtmlConfig = [
+ 'assets_mode' => AssetsMode::CDN,
+ 'swagger_ui_config' => [],
+ 'server_url' => null,
+ ];
+
public function __construct(RenderOpenApi $renderOpenApi)
{
$this->renderOpenApi = $renderOpenApi;
@@ -36,9 +46,18 @@ class DumpCommand extends Command
*/
protected function configure()
{
+ $availableFormats = $this->renderOpenApi->getAvailableFormats();
$this
- ->setDescription('Dumps documentation in OpenAPI JSON format')
+ ->setDescription('Dumps documentation in OpenAPI JSON format or HTML')
->addOption('area', '', InputOption::VALUE_OPTIONAL, '', 'default')
+ ->addOption(
+ 'format',
+ '',
+ InputOption::VALUE_REQUIRED,
+ 'Output format like: '.implode(', ', $availableFormats),
+ RenderOpenApi::JSON
+ )
+ ->addOption('html-config', '', InputOption::VALUE_REQUIRED, '', json_encode($this->defaultHtmlConfig))
->addOption('no-pretty', '', InputOption::VALUE_NONE, 'Do not pretty format output')
;
}
@@ -49,11 +68,19 @@ class DumpCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output)
{
$area = $input->getOption('area');
+ $format = $input->getOption('format');
- $options = [
- 'no-pretty' => $input->hasParameterOption(['--no-pretty']),
- ];
- $docs = $this->renderOpenApi->render(RenderOpenApi::JSON, $area, $options);
+ $options = [];
+ if (RenderOpenApi::HTML === $format) {
+ $rawHtmlConfig = json_decode($input->getOption('html-config'), true);
+ $options = is_array($rawHtmlConfig) ? $rawHtmlConfig : $this->defaultHtmlConfig;
+ } elseif (RenderOpenApi::JSON === $format) {
+ $options = [
+ 'no-pretty' => $input->hasParameterOption(['--no-pretty']),
+ ];
+ }
+
+ $docs = $this->renderOpenApi->render($format, $area, $options);
$output->writeln($docs, OutputInterface::OUTPUT_RAW);
return 0;
diff --git a/Controller/SwaggerUiController.php b/Controller/SwaggerUiController.php
index 4edad7f..1d4cca4 100644
--- a/Controller/SwaggerUiController.php
+++ b/Controller/SwaggerUiController.php
@@ -12,6 +12,7 @@
namespace Nelmio\ApiDocBundle\Controller;
use InvalidArgumentException;
+use Nelmio\ApiDocBundle\Render\Html\AssetsMode;
use Nelmio\ApiDocBundle\Render\RenderOpenApi;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -35,6 +36,7 @@ final class SwaggerUiController
$response = new Response(
$this->renderOpenApi->render(RenderOpenApi::HTML, $area, [
'server_url' => '' !== $request->getBaseUrl() ? $request->getSchemeAndHttpHost().$request->getBaseUrl() : null,
+ 'assets_mode' => AssetsMode::BUNDLE,
]),
Response::HTTP_OK,
['Content-Type' => 'text/html']
diff --git a/Render/Html/AssetsMode.php b/Render/Html/AssetsMode.php
new file mode 100644
index 0000000..2bbdf5a
--- /dev/null
+++ b/Render/Html/AssetsMode.php
@@ -0,0 +1,19 @@
+assetExtension = $assetExtension;
+ $this->defaultAssetsMode = $defaultAssetsMode;
+ }
+
+ public function __invoke($asset, $forcedMode = null)
+ {
+ $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));
+ } else {
+ return $this->assetExtension->getAssetUrl(sprintf('bundles/nelmioapidoc/%s', $asset));
+ }
+ }
+}
diff --git a/Render/Html/HtmlOpenApiRenderer.php b/Render/Html/HtmlOpenApiRenderer.php
index 32417be..5bb8645 100644
--- a/Render/Html/HtmlOpenApiRenderer.php
+++ b/Render/Html/HtmlOpenApiRenderer.php
@@ -16,7 +16,9 @@ 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
{
@@ -24,13 +26,18 @@ class HtmlOpenApiRenderer implements OpenApiRenderer
* @var Environment|\Twig_Environment
*/
private $twig;
+ /**
+ * @var AssetExtension
+ */
+ private $assetExtension;
- public function __construct($twig)
+ public function __construct($twig, AssetExtension $assetExtension)
{
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;
}
public function getFormat(): string
@@ -42,15 +49,33 @@ class HtmlOpenApiRenderer implements OpenApiRenderer
{
$options += [
'server_url' => null,
+ 'assets_mode' => AssetsMode::CDN,
+ 'swagger_ui_config' => [],
];
- if ($options['server_url']) {
- $spec->servers = [new Server(['url' => $options['server_url']])];
- }
+ $this->twig->addFunction(
+ new TwigFunction(
+ 'nelmioAsset',
+ new GetNelmioAsset($this->assetExtension, $options['assets_mode'])
+ )
+ );
return $this->twig->render(
'@NelmioApiDoc/SwaggerUi/index.html.twig',
- ['swagger_data' => ['spec' => json_decode($spec->toJson(), true)]]
+ [
+ 'swagger_data' => ['spec' => $this->createJsonSpec($spec, $options['server_url'])],
+ 'assets_mode' => $options['assets_mode'],
+ 'swagger_ui_config' => $options['swagger_ui_config'],
+ ]
);
}
+
+ private function createJsonSpec(OpenApi $spec, $serverUrl)
+ {
+ if ($serverUrl) {
+ $spec->servers = [new Server(['url' => $serverUrl])];
+ }
+
+ return json_decode($spec->toJson(), true);
+ }
}
diff --git a/Render/RenderOpenApi.php b/Render/RenderOpenApi.php
index aace14f..1407b67 100644
--- a/Render/RenderOpenApi.php
+++ b/Render/RenderOpenApi.php
@@ -34,6 +34,11 @@ class RenderOpenApi
}
}
+ public function getAvailableFormats(): array
+ {
+ return array_keys($this->openApiRenderers);
+ }
+
/**
* @throws InvalidArgumentException If the area to dump is not valid
*/
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index 47174fd..e0127ae 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -33,6 +33,7 @@