Skip to content

feat: allow for order of rendering be overridden in docs #502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions tools/api-docs-generator/generator/reference_docs.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package generator

import (
"cmp"
"fmt"
"os"
"path"
"path/filepath"
"slices"
"sort"
"strconv"
"strings"

"github.com/getkin/kin-openapi/openapi3"
Expand All @@ -20,6 +23,7 @@ type operationPath struct {
specPath string
method string
docsHint string
order int
}

func GenerateReferenceDocs(cfg *config.Config, docsBasePath string) error {
Expand All @@ -35,6 +39,9 @@ func GenerateReferenceDocs(cfg *config.Config, docsBasePath string) error {
}

for label, operations := range aggregatedDocs {
slices.SortFunc(operations, func(i, j operationPath) int {
return cmp.Compare(i.order, j.order)
})
destinationPath := path.Join(docsBasePath, cfg.Output.APIReferencePath, labelToFileName(label))
summary = append(summary, fmt.Sprintf("* [%s](%s)\n", label, path.Join(cfg.Output.APIReferencePath, labelToFileName(label))))

Expand Down Expand Up @@ -139,14 +146,23 @@ func processOperation(pathURL string,
operation *openapi3.Operation,
spec config.Spec,
specDocs map[string][]operationPath) error {
var order int
for _, tag := range operation.Tags {
if tag == "OpenAPI" {
continue
}

if snykDocsExtension, ok := operation.Extensions["x-snyk-documentation"]; ok && snykDocsExtension != nil {
var err error
tag, err = extractCategoryNameFromExtension(snykDocsExtension)
renamedTag, err := extractCategoryNameFromExtension(snykDocsExtension)
if err != nil {
return err
}
if renamedTag != "" {
tag = renamedTag
}

order, err = extractOrderFromExtension(snykDocsExtension)
if err != nil {
return err
}
Expand All @@ -164,6 +180,7 @@ func processOperation(pathURL string,
specPath: spec.Path,
method: method,
docsHint: spec.DocsHint,
order: order,
})
}
return nil
Expand All @@ -181,14 +198,30 @@ func isBeta(operation *openapi3.Operation) bool {
return stabilityStr == "beta"
}

func extractOrderFromExtension(extension interface{}) (int, error) {
extensionMap, worked := extension.(map[string]interface{})
if !worked {
return 0, fmt.Errorf("failed to parse docs extension as an object")
}
orderValue, worked := extensionMap["order"].(string)
if !worked {
return 0, nil
}
orderAsInt, err := strconv.Atoi(orderValue)
if err != nil {
return 0, fmt.Errorf("x-snyk-documentation extension order field not a int, %w", err)
}
return orderAsInt, nil
}

func extractCategoryNameFromExtension(extension interface{}) (string, error) {
extensionMap, worked := extension.(map[string]interface{})
if !worked {
return "", fmt.Errorf("failed to parse docs extension as an object")
}
categoryValue, worked := extensionMap["category"].(string)
if !worked {
return "", fmt.Errorf("x-snyk-documentation extension category field not a string")
return "", nil
}
return categoryValue, nil
}
Expand Down
33 changes: 33 additions & 0 deletions tools/api-docs-generator/generator/reference_docs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,39 @@ func Test_aggregateSpecs(t *testing.T) {
},
wantErr: assert.NoError,
},
{
name: "uses override order if present",
args: args{
cfg: &config.Config{
Specs: []config.Spec{
{
Path: "spec_with_order_override.yaml",
},
},
},
docsBasePath: "../testdata/reference_docs/",
},
want: map[string][]operationPath{
"test": {
{
method: "POST",
specPath: "spec_with_order_override.yaml",
pathURL: "/test",
},
{
method: "POST",
specPath: "spec_with_order_override.yaml",
pathURL: "/test/1",
},
{
method: "POST",
specPath: "spec_with_order_override.yaml",
pathURL: "/test/2",
},
},
},
wantErr: assert.NoError,
},
{
name: "filters out beta paths",
args: args{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
openapi: 3.0.3
info:
title: Test
contact: {}
version: 3.0.0
description: Sample API
servers:
- url: /test
description: Test
tags:
- name: Test
description: test
paths:
/test:
post:
x-snyk-api-stability: ga
x-snyk-documentation:
order: -1
tags:
- test
description: test
operationId: test
requestBody:
content:
application/vnd.api+json:
schema:
type: object
properties:
prop1:
type: string
responses:
"201":
description: success
content:
application/vnd.api+json:
schema:
type: object
location:
schema:
type: string
/test/1:
post:
x-snyk-api-stability: ga
tags:
- test
description: test
operationId: test
requestBody:
content:
application/vnd.api+json:
schema:
type: object
properties:
prop1:
type: string
responses:
"201":
description: success
content:
application/vnd.api+json:
schema:
type: object
location:
schema:
type: string
/test/2:
post:
x-snyk-api-stability: ga
tags:
- test
description: test
operationId: test
requestBody:
content:
application/vnd.api+json:
schema:
type: object
properties:
prop1:
type: string
responses:
"201":
description: success
content:
application/vnd.api+json:
schema:
type: object
location:
schema:
type: string