Skip to content

Commit

Permalink
link external documentation and render markdown description
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffersongirao authored and dweber019 committed Jun 8, 2024
1 parent bd61514 commit 56e88f2
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 35 deletions.
11 changes: 11 additions & 0 deletions plugins/api-docs-spectral-linter/dev/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import openapiApiEntity from './openapi-example-api.yaml';
import openapiZalandoApiEntity from './openapi-zalando-example-api.yaml';
// @ts-ignore
import openapiBaloiseApiEntity from './openapi-baloise-example-api.yaml';
// @ts-ignore
import openapiOwaspApiEntity from './openapi-owasp-example-api.yaml';

const mockConfig = new MockConfigApi({
spectralLinter: {
Expand Down Expand Up @@ -69,4 +71,13 @@ createDevApp()
title: 'Open API - Baloise',
path: '/open-api-baloise',
})
.addPage({
element: (
<EntityProvider entity={openapiOwaspApiEntity as any as Entity}>
<EntityApiDocsSpectralLinterContent />
</EntityProvider>
),
title: 'Open API - OWASP',
path: '/open-api-owasp',
})
.render();
126 changes: 126 additions & 0 deletions plugins/api-docs-spectral-linter/dev/openapi-owasp-example-api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: petstore-owasp-rules
description: The petstore API
tags:
- store
- rest
annotations:
backstage.io/spectral-ruleset-url: https://unpkg.com/@stoplight/[email protected]/dist/ruleset.mjs
spec:
type: openapi
lifecycle: experimental
owner: team-c
definition: |
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
10 changes: 10 additions & 0 deletions plugins/api-docs-spectral-linter/src/api/LinterClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ export class LinterClient implements LinterApi {
severity: diagnosticItem.severity,
path: diagnosticItem.path.map(item => item.toString()),
code: diagnosticItem.code,
ruleDocumentationUrl: ruleDocumentationUrl(spectral, diagnosticItem.code),
ruleDescription: ruleDescription(spectral, diagnosticItem.code)
})),
};
}
Expand All @@ -124,3 +126,11 @@ export class LinterClient implements LinterApi {
return isApiDocsSpectralLinterAvailable(entity);
}
}

function ruleDocumentationUrl(spectral: Spectral, code: string | number): string | undefined {
return spectral.ruleset?.rules[code].documentationUrl || undefined
}

function ruleDescription(spectral: Spectral, code: string | number): string | undefined {
return spectral.ruleset?.rules[code].description || undefined
}
4 changes: 4 additions & 0 deletions plugins/api-docs-spectral-linter/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export type LinterResultData = {
*/
severity: number;

ruleDocumentationUrl?: string;

ruleDescription?: string;

/**
* The path in content.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import React, { useState } from 'react';
import {
CodeSnippet,
InfoCard,
MarkdownContent,
Progress,
WarningPanel,
} from '@backstage/core-components';
Expand Down Expand Up @@ -113,41 +114,50 @@ export const EntityApiDocsSpectralLinterContent = () => {
value.data.map((ruleResult, idx) => (
<Grid key={idx} container spacing={2}>
<Grid item xs={12}>
<Alert
severity={getSeverity(ruleResult.severity)}
variant="outlined"
>
<AlertTitle>
{ruleResult.message} ({ruleResult.code})
<IconButton
aria-label="expand"
onClick={handleChange(`alert${idx}`)}
className={classes.alertButton}
>
{`alert${idx}` === expanded ? (
<ExpandLessIcon />
) : (
<ExpandMoreIcon />
)}
</IconButton>
</AlertTitle>
{`alert${idx}` === expanded && (
<CodeSnippet
text={previewContent(
entity.spec.definition,
ruleResult.linePosition.start,
ruleResult.linePosition.end,
ruleResult.path?.join(' / ') || 'unknown',
)}
language="yaml"
customStyle={{
background: 'transparent',
margin: '0',
padding: '0.5em 0',
}}
/>
)}
</Alert>
<Alert
severity={getSeverity(ruleResult.severity)}
variant="outlined"
>
<AlertTitle>
{ruleResult.message} ({ruleResult.code})
<IconButton
aria-label="expand"
onClick={handleChange(`alert${idx}`)}
className={classes.alertButton}
>
{`alert${idx}` === expanded ? (
<ExpandLessIcon />
) : (
<ExpandMoreIcon />
)}
</IconButton>
</AlertTitle>
{`alert${idx}` === expanded && (
<InfoCard deepLink={
ruleResult.ruleDocumentationUrl ?
{
title:"Documentation",
link: ruleResult.ruleDocumentationUrl
} : undefined
}>
<MarkdownContent content={ ruleResult.ruleDescription || "" }></MarkdownContent>
<CodeSnippet
text={previewContent(
entity.spec.definition,
ruleResult.linePosition.start,
ruleResult.linePosition.end,
ruleResult.path?.join(' / ') || 'unknown',
)}
language="yaml"
customStyle={{
background: 'transparent',
margin: '0',
padding: '0.5em 0',
}}
/>
</InfoCard>
)}
</Alert>
</Grid>
</Grid>
))
Expand Down

0 comments on commit 56e88f2

Please sign in to comment.