I think it would be nice to have a new mix task to rely on the output of the existing task and generate a markdown file that ExDoc can parse and include in our statically generated documentation. I've experimented with this locally and came up with something like this (might not match this project patterns):
defmodule Mix.Tasks.GenerateSwaggerDoc do
@shortdoc "Generate an OpenAPI specification file for the REST API."
@moduledoc """
Generate an OpenAPI specification file for the REST API.
Usage:
```
$ mix generate_swagger_doc <output_file>
```
"""
use Mix.Task
alias Mix.Tasks.Openapi.Spec.Json
@contents """
<head>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@4.4.1/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@4.4.1/swagger-ui-bundle.js" crossorigin></script>
<script src="https://unpkg.com/swagger-ui-dist@4.4.1/swagger-ui-standalone-preset.js" crossorigin></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
spec: <%= json_spec %>,
dom_id: '#swagger-ui',
});
};
</script>
</body>
"""
@args [output_file: :string, spec: :string]
@args_aliases [o: :output_file, s: :spec]
@default_file "guides/swagger.md"
@impl Mix.Task
@spec run([String.t()]) :: any()
def run(args) do
{parsed_args, _rest} = OptionParser.parse!(args, switches: @args, aliases: @args_aliases)
output_file = Keyword.get(parsed_args, :output_file, @default_file)
Mix.Task.run("app.start")
# generate the openapi.json file
Json.run(["--spec", "PhoenixAppWeb.ApiSpec"])
json_spec = File.read!("openapi.json")
:ok = File.write!(output_file, EEx.eval_string(@contents, json_spec: json_spec))
end
end
and can be added to the mix.exs docs as an extra:
# mix.exs
def project do
...
docs: [extras: ["guides/swagger.md"]]
...
end
Happy to contribute this back if there's interest and openness to it.
I think it would be nice to have a new mix task to rely on the output of the existing task and generate a markdown file that ExDoc can parse and include in our statically generated documentation. I've experimented with this locally and came up with something like this (might not match this project patterns):
and can be added to the
mix.exsdocs as an extra:Happy to contribute this back if there's interest and openness to it.