Pre-requirements
HTML Genration tools
Development tools
- These reference links are omited
- Docker
- Golang
Optional:
How to generate the single API HTML
This page show how to generate an API html file int the following.
- Write each API definition
- Generate OpenAPI spec file
- Run a linter
- Convert to some HTML files
To create an API html, these commands is used and this is Makefile.
DEF_FILE=oas.jsonnet
OAS_JSON=swagger.json
OAS_YAML=swagger.yaml
gen:
jsonnet $(DEF_FILE) > $(OAS_JSON)
cat $(OAS_JSON) | yq -p json '.' > $(OAS_YAML)
lint:
docker run --rm --tty -v "$(PWD):/data:ro" ibmdevxsdk/openapi-validator:latest $(OAS_YAML)
html: html-redoc html-elements
@echo "done"
html-redoc:
docker run --rm -v $(PWD):/spec redocly/cli build-docs $(OAS_YAML) --output=redoc-api.html
html-elements:
go run elements-gen.go $(OAS_JSON) > elements-api.html
Prep a directory
# Input
<path to dir>/
Makefile ... each command for the Html file generation
oas.jsonnet ... jsonnet file OpenAPI spec definition to organize each definition file
elements-gen.go ... a script of the spotlight elements html file
components/ ... some spec definitions for the schema, parameters and more
common.yaml
todo.yaml
paths/ ... each endpoints definitions
todo.yaml
user.yaml
# Output
swagger.json|yaml ... Generated by Jsonnet
elements-api.html ... Generated by
dockly-api.html
Define API of openapi format
This section explains each definition details.
A overview part
{
openapi: '3.0.0',
info : {
title: 'Example OAS',
description: "example openapi",
version: '0.0.2',
},
}
A schema definition
components/common.yamlGeneralError:
type: object
properties:
code:
type: string
message:
type: string
TODO:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
text:
type: string
A Endpoint part
paths/todo.yaml/todos:
get:
summary: list of todo items
parameters:
- in: query
name: offset
schema:
type: integer
- in: query
name: limit
schema:
type: integer
responses:
"200":
description: Items
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/TODO'
Generate the API defininion
To generate OpenAPI spec definition file, organize some definition files in the Jsonnet file
oas.jsonnnet// NOTE: Jsonnet doesn't allow dynamic import. local components = [ importstr "./components/schema.yaml", importstr "./components/todo.yaml" ]; local endpoints = [ importstr "./paths/todo.yaml" ]; local to_def(arr) = std.foldl(function(a, x) a + std.parseYaml( x ) , arr, {}); { openapi: '3.0.0', info : { title: 'Example OAS', description: "example openapi", version: '0.0.2', }, components: { schemas: to_def(components), }, paths: to_def(endpoints) }
Several json and yaml files are assembled by the Jsonnet command.
Makefile# Create the OpenAPI spec jsonnet oas.jsonnet > swagger.json # Convert to yaml file, if need cat swagger.json | yq '.' -p json > swagger.yaml
Lint the definition
- To verify the generated spec file, run a linter
docker run --rm --tty -v "$(PWD):/data:ro" ibmdevxsdk/openapi-validator:latest swagger.yaml
Convert to HTML
For some HTML files, the Redocly CLI and spotligt-elements
# redoc html generation command docker run --rm -v $(PWD):/spec redocly/cli build-docs $(OAS_YAML) --output=redoc-api.html # Run go script to generate html (golang script code is at the bottom) go run elements-gen.go $(OAS_JSON) > elements-api.html # Check on the Browser python3 -m http.server 5200 # localhost:5200/redoc-api.html # localhost:5200/elements-api.html
Redoc output
Elements output
Golang Script
package main
import (
"os"
"flag"
"log"
"html/template"
)
const (
elementDoc = `
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Elements in HTML</title>
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
</head>
<body>
<elements-api
id="docs"
router="hash"
/>
<script type="application/json" id="oas-data">
{{ .API }} </script>
<script>
(() => {
const data = document.getElementById('oas-data');
const docs = document.getElementById('docs');
docs.apiDescriptionDocument = data.innerHTML;
})();
</script>
</body>
</html>
`
)
func main() {
flag.Parse()
jsonData, err := os.ReadFile(flag.Arg(0))
if err != nil {
log.Fatalf("can't read file %v", err)
}
tmp := template.Must(template.New("html").Parse(elementDoc))
tmp.Execute(os.Stdout, map[string]any{
"API": template.JS(jsonData),
})
}