Introduce experimental OpenAPI shortcode

This commit is contained in:
Alex Shpak
2026-05-22 14:06:48 +02:00
parent 118c5354bb
commit 1d38cd0183
8 changed files with 683 additions and 35 deletions
+261
View File
@@ -0,0 +1,261 @@
{
"openapi": "3.1.0",
"info": {
"title": "Tic Tac Toe",
"description": "This API allows writing down marks on a Tic Tac Toe board\nand requesting the state of the board or of individual squares.\n",
"version": "1.0.0"
},
"tags": [
{
"name": "Gameplay"
}
],
"paths": {
"/board": {
"get": {
"summary": "Get the whole board",
"description": "Retrieves the current state of the board and the winner.",
"tags": ["Gameplay"],
"operationId": "get-board",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/status"
}
}
}
}
},
"security": [
{
"defaultApiKey": []
},
{
"app2AppOauth": ["board:read"]
}
]
}
},
"/board/{row}/{column}": {
"parameters": [
{
"$ref": "#/components/parameters/rowParam"
},
{
"$ref": "#/components/parameters/columnParam"
}
],
"get": {
"summary": "Get a single board square",
"description": "Retrieves the requested square.",
"tags": ["Gameplay"],
"operationId": "get-square",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/mark"
}
}
}
},
"400": {
"description": "The provided parameters are incorrect",
"content": {
"text/html": {
"schema": {
"$ref": "#/components/schemas/errorMessage"
},
"example": "Illegal coordinates"
}
}
}
},
"security": [
{
"bearerHttpAuthentication": []
},
{
"user2AppOauth": ["board:read"]
}
]
},
"put": {
"summary": "Set a single board square",
"description": "Places a mark on the board and retrieves the whole board and the winner (if any).",
"tags": ["Gameplay"],
"operationId": "put-square",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/mark"
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/status"
}
}
}
},
"400": {
"description": "The provided parameters are incorrect",
"content": {
"text/html": {
"schema": {
"$ref": "#/components/schemas/errorMessage"
},
"examples": {
"illegalCoordinates": {
"value": "Illegal coordinates."
},
"notEmpty": {
"value": "Square is not empty."
},
"invalidMark": {
"value": "Invalid Mark (X or O)."
}
}
}
}
}
},
"security": [
{
"bearerHttpAuthentication": []
},
{
"user2AppOauth": ["board:write"]
}
]
}
}
},
"components": {
"parameters": {
"rowParam": {
"description": "Board row (vertical coordinate)",
"name": "row",
"in": "path",
"required": true,
"schema": {
"$ref": "#/components/schemas/coordinate"
}
},
"columnParam": {
"description": "Board column (horizontal coordinate)",
"name": "column",
"in": "path",
"required": true,
"schema": {
"$ref": "#/components/schemas/coordinate"
}
}
},
"schemas": {
"errorMessage": {
"type": "string",
"maxLength": 256,
"description": "A text message describing an error"
},
"coordinate": {
"type": "integer",
"minimum": 1,
"maximum": 3,
"example": 1
},
"mark": {
"type": "string",
"enum": [".", "X", "O"],
"description": "Possible values for a board square. `.` means empty square.",
"example": "."
},
"board": {
"type": "array",
"maxItems": 3,
"minItems": 3,
"items": {
"type": "array",
"maxItems": 3,
"minItems": 3,
"items": {
"$ref": "#/components/schemas/mark"
}
}
},
"winner": {
"type": "string",
"enum": [".", "X", "O"],
"description": "Winner of the game. `.` means nobody has won yet.",
"example": "."
},
"status": {
"type": "object",
"properties": {
"winner": {
"$ref": "#/components/schemas/winner"
},
"board": {
"$ref": "#/components/schemas/board"
}
}
}
},
"securitySchemes": {
"defaultApiKey": {
"description": "API key provided in console",
"type": "apiKey",
"name": "api-key",
"in": "header"
},
"basicHttpAuthentication": {
"description": "Basic HTTP Authentication",
"type": "http",
"scheme": "Basic"
},
"bearerHttpAuthentication": {
"description": "Bearer token using a JWT",
"type": "http",
"scheme": "Bearer",
"bearerFormat": "JWT"
},
"app2AppOauth": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "https://learn.openapis.org/oauth/2.0/token",
"scopes": {
"board:read": "Read the board"
}
}
}
},
"user2AppOauth": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl": "https://learn.openapis.org/oauth/2.0/auth",
"tokenUrl": "https://learn.openapis.org/oauth/2.0/token",
"scopes": {
"board:read": "Read the board",
"board:write": "Write to the board"
}
}
}
}
}
}
}
+13 -33
View File
@@ -5,62 +5,42 @@ layout: landing
<br />
# Hugo Book {anchor=false}
{{% columns %}}
- Documentation theme for [Hugo](https://gohugo.io) as simple as plain book.
Hugo-Book theme is designed to be easy to read, write, navigate and maintain.
It is an attempt to create a sustainable web project.
Documentation theme for [Hugo](https://gohugo.io) as simple as plain book.
{{<button href="/docs/getting-started/introduction">}}Explore{{</button>}}
Hugo-Book theme is designed to be easy to read, write, navigate and maintain.
It is an attempt to create a sustainable web project.
- ```shell
# TL;DR
git clone https://github.com/alex-shpak/hugo-book-starter documentation
cd documentation
git submodule update --init --remote
hugo server --minify
```
{{% /columns %}}
{{<button href="/docs/getting-started/introduction">}}Explore{{</button>}}
<br />
<br />
{{% columns %}}
- {{< card >}}
### Probably fast {anchor=false}
- ### Probably fast {anchor=false}
Built on Hugo static site generator. "The worlds fastest framework for building websites".
{{< /card >}}
- {{< card >}}
### 50% JS free {anchor=false}
- ### 50% JS free {anchor=false}
All important features are working even with JavaScript disabled in the browser, including interactive shortcodes.
{{< /card >}}
- {{< card >}}
### Minimalistic {anchor=false}
- ### Minimalistic {anchor=false}
For real, it is very minimalistic, black on white. No extra tools are needed to build the site, only Hugo. No heavy JS or CSS frameworks included.
{{< /card >}}
{{% /columns %}}
{{% columns %}}
- {{< card >}}
### Shortcodes {anchor=false}
- ### Shortcodes {anchor=false}
Pretty good shortcodes are included to enhance content:
[Columns](/docs/content/shortcodes/columns/),
[Cards](/docs/content/shortcodes/cards/),
[Cards](/docs/content/shortcodes/experimental/cards/),
[Tabs](/docs/content/shortcodes/tabs/),
[Images](/docs/content/shortcodes/images/),
[Images](/docs/content/shortcodes/experimental/images/),
[Asciinema](/docs/content/shortcodes/asciinema/),
[KaTex](/docs/content/shortcodes/katex/),
[Mermaid](/docs/content/shortcodes/mermaid/) and others.
{{< /card >}}
- {{< card >}}
### Even more {anchor=false}
- ### Even more {anchor=false}
Do people actually read these? I thought it was just a visual filler. But there is full-text search and multi-language support.
{{< /card >}}
- {{< card >}}
### Made to be extendable {anchor=false}
- ### Made to be extendable {anchor=false}
There are multiple points to inject own styles and templates to make it your own.
{{< /card >}}
{{% /columns %}}
@@ -0,0 +1,3 @@
---
bookCollapseSection: true
---
@@ -1,6 +1,6 @@
# Cards
Content blocks with optional images and links. Often used with [Columns](/docs/content/shortcodes/columns) for grid layouts.
Content blocks with optional images and links. Often used with [Columns](/docs/content/shortcodes/columns/) for grid layouts.
## Syntax
@@ -18,7 +18,7 @@ Markdown content
Cards can display an image above the content.
{{< /card >}}
- {{< card href="/docs/content/shortcodes/cards" >}}
- {{< card href="/docs/content/shortcodes/experimental/cards/" >}}
### With Link {anchor=false}
When `href` is set, the entire card becomes clickable.
{{< /card >}}
@@ -0,0 +1,19 @@
---
title: OpenAPI
---
# OpenAPI
Renders an OpenAPI 3.x specification as a documentation page. Operations are grouped by their first tag.
## Syntax
```tpl
{{%/* openapi src="spec.json" */%}}
```
The spec file is loaded via `resources.Get`, so the path is relative to the site's `assets/` directory. JSON and YAML are both supported.
## Example
{{% openapi src="tictactoe.json" %}}