-
-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 48b3129
Showing
23 changed files
with
1,366 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
const _ = require('lodash'); | ||
const Markdown = require('markdown-it'); | ||
const OpenAPISampler = require('openapi-sampler'); | ||
|
||
module.exports = ({ Nunjucks }) => { | ||
Nunjucks.addFilter('split', (string, separator) => { | ||
if (typeof string !== 'string') return string; | ||
const regex = new RegExp(separator, 'g'); | ||
return string.split(regex); | ||
}); | ||
|
||
Nunjucks.addFilter('firstKey', (obj) => { | ||
if (!obj) return ''; | ||
return Object.keys(obj)[0]; | ||
}); | ||
|
||
Nunjucks.addFilter('isExpandable', (obj) => { | ||
if ( | ||
obj.type() === 'object' || | ||
obj.type() === 'array' || | ||
(obj.oneOf() && obj.oneOf().length) || | ||
(obj.anyOf() && obj.anyOf().length) || | ||
(obj.allOf() && obj.allOf().length) || | ||
obj.items() || | ||
obj.additionalItems() || | ||
(obj.properties() && Object.keys(obj.properties()).length) || | ||
obj.additionalProperties() || | ||
(obj.extensions() && Object.keys(obj.extensions()).filter(e => !e.startsWith('x-parser-')).length) || | ||
obj.patternProperties() | ||
) return true; | ||
|
||
return false; | ||
}); | ||
|
||
/** | ||
* Check if there is a channel which does not have one of the tags specified. | ||
*/ | ||
Nunjucks.addFilter('containTags', (object, tagsToCheck) => { | ||
if (!object) { | ||
throw new Error("object for containsTag was not provided?"); | ||
} | ||
|
||
if (!tagsToCheck) { | ||
throw new Error("tagsToCheck for containsTag was not provided?"); | ||
} | ||
|
||
//Ensure if only 1 tag are provided it is converted to array. | ||
if (tagsToCheck && !Array.isArray(tagsToCheck)) { | ||
tagsToCheck = [tagsToCheck]; | ||
} | ||
|
||
//Check if pubsub contain one of the tags to check. | ||
let check = (tag) => { | ||
let found = false; | ||
for (let tagToCheckIndex in tagsToCheck) { | ||
let tagToCheck = tagsToCheck[tagToCheckIndex]._json; | ||
if (tagToCheck.name === tag.name) { | ||
found = true; | ||
} | ||
} | ||
return found; | ||
}; | ||
|
||
//Ensure tags are checked for the group tags | ||
let containTags = object._json.tags ? object._json.tags.find(check) != null : false; | ||
return containTags; | ||
}); | ||
|
||
/** | ||
* Check if there is a channel which does not have one of the tags specified. | ||
*/ | ||
Nunjucks.addFilter('containNoTag', (channels, tagsToCheck) => { | ||
if (!channels) { | ||
throw new Error("Channels for containNoTag was not provided?"); | ||
} | ||
for (let channelIndex in channels) { | ||
let channel = channels[channelIndex]._json; | ||
//Check if the channel contains publish or subscribe which does not contain tags | ||
if (channel.publish && (!channel.publish.tags || channel.publish.tags.length == 0) || | ||
channel.subscribe && (!channel.subscribe.tags || channel.subscribe.tags.length == 0) | ||
) { | ||
//one does not contain tags | ||
return true; | ||
} | ||
|
||
//Check if channel publish or subscribe does not contain one of the tags to check. | ||
let check = (tag) => { | ||
let found = false; | ||
for (let tagToCheckIndex in tagsToCheck) { | ||
let tagToCheck = tagsToCheck[tagToCheckIndex]._json; | ||
if (tagToCheck.name === tag.name) { | ||
found = true; | ||
} | ||
} | ||
return found; | ||
}; | ||
|
||
//Ensure pubsub tags are checked for the group tags | ||
let publishContainsNoTag = channel.publish && channel.publish.tags ? channel.publish.tags.find(check) == null : false; | ||
if (publishContainsNoTag === true) return true; | ||
let subscribeContainsNoTag = channel.subscribe && channel.subscribe.tags ? channel.subscribe.tags.find(check) == null : false; | ||
if (subscribeContainsNoTag === true) return true; | ||
} | ||
return false; | ||
}); | ||
|
||
Nunjucks.addFilter('isArray', (arr) => { | ||
return Array.isArray(arr); | ||
}); | ||
|
||
Nunjucks.addFilter('isObject', (obj) => { | ||
return typeof obj === 'object' && obj !== null; | ||
}); | ||
|
||
Nunjucks.addFilter('contains', (array, element) => { | ||
if (!array || !Array.isArray(array)) return false; | ||
return array.includes(element); | ||
}); | ||
|
||
Nunjucks.addFilter('log', (anything) => { | ||
console.log(anything); | ||
}); | ||
|
||
Nunjucks.addFilter('markdown2html', (md) => { | ||
return Markdown().render(md || ''); | ||
}); | ||
|
||
Nunjucks.addFilter('getPayloadExamples', (msg) => { | ||
if (Array.isArray(msg.examples()) && msg.examples().find(e => e.payload)) { | ||
// Instead of flat or flatmap use this. | ||
return _.flatMap(msg.examples().map(e => e.payload).filter(Boolean)); | ||
} | ||
|
||
if (msg.payload() && msg.payload().examples()) { | ||
return msg.payload().examples(); | ||
} | ||
}); | ||
|
||
Nunjucks.addFilter('getHeadersExamples', (msg) => { | ||
if (Array.isArray(msg.examples()) && msg.examples().find(e => e.headers)) { | ||
// Instead of flat or flatmap use this. | ||
return _.flatMap(msg.examples().map(e => e.headers).filter(Boolean)); | ||
} | ||
|
||
if (msg.headers() && msg.headers().examples()) { | ||
return msg.headers().examples(); | ||
} | ||
}); | ||
|
||
Nunjucks.addFilter('generateExample', (schema) => { | ||
return JSON.stringify(OpenAPISampler.sample(schema) || '', null, 2); | ||
}); | ||
|
||
Nunjucks.addFilter('nonParserExtensions', (schema) => { | ||
if (!schema || !schema.extensions || typeof schema.extensions !== 'function') return new Map(); | ||
const extensions = Object.entries(schema.extensions()); | ||
return new Map(extensions.filter(e => !e[0].startsWith('x-parser-')).filter(Boolean)); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{% include ".partials/introduction.html" %} | ||
{% if asyncapi.hasServers() %} | ||
{% include ".partials/servers.html" %} | ||
{% endif %} | ||
{% if asyncapi.hasChannels() %} | ||
{% include ".partials/operations.html" %} | ||
{% endif %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{% macro example(msg, channelName) %} | ||
|
||
<form> | ||
<input type="radio" checked id="example-payload-{{channelName}}-{{msg.uid()}}" name="tab" class="examples-payload-tab hidden" {% if not msg.payload() %}disabled{% endif %}/> | ||
<label for="example-payload-{{channelName}}-{{msg.uid()}}" class="py-1 px-2 mr-2 mb-4 text-grey-lightest text-sm border rounded focus:outline-none cursor-pointer {% if not msg.payload() %}text-grey-dark border-grey-dark opacity-25{% else %}text-grey-lightest{% endif %}" {% if not msg.payload() %}title="This message does not have a payload"{% endif %}>Payload</label> | ||
|
||
<input type="radio" id="example-headers-{{channelName}}-{{msg.uid()}}" name="tab" class="examples-headers-tab hidden" {% if not msg.headers() %}disabled{% endif %} /> | ||
<label for="example-headers-{{channelName}}-{{msg.uid()}}" | ||
class="py-1 px-2 mr-2 mb-4 text-sm border rounded focus:outline-none cursor-pointer {% if not msg.headers() %}text-grey-dark border-grey-dark opacity-25{% else %}text-grey-lightest{% endif %}" {% if not msg.headers() %}title="This message does not have headers"{% endif %}>Headers</label> | ||
|
||
<div class="payload-examples mt-4"> | ||
{% if msg | getPayloadExamples | length %} | ||
{% for ex in msg | getPayloadExamples %} | ||
<h6 class="text-xs font-bold text-grey-darker">Example #{{loop.index}}</h6> | ||
<pre class="hljs mb-4 border border-grey-darkest rounded"><code>{{ex | dump(2) | safe }}</code></pre> | ||
{% endfor %} | ||
{% elif msg.payload() %} | ||
<pre class="hljs mb-4 border border-grey-darkest rounded"><code>{{ msg.payload().json() | generateExample | safe }}</code></pre> | ||
<h6 class="text-xs font-bold text-grey-darker italic">This example has been generated automatically.</h6> | ||
{% endif %} | ||
</div> | ||
|
||
<div class="headers-examples mt-4"> | ||
{% if msg | getHeadersExamples | length %} | ||
{% for ex in msg | getHeadersExamples %} | ||
<h6 class="text-xs font-bold text-grey-darker">Example #{{loop.index}}</h6> | ||
<pre class="hljs mb-4 border border-grey-darkest rounded"><code>{{ ex | dump(2) | safe }}</code></pre> | ||
{% endfor %} | ||
{% elif msg.headers() %} | ||
<pre class="hljs mb-4 border border-grey-darkest rounded"><code>{{ msg.headers().json() | generateExample | safe }}</code></pre> | ||
<h6 class="text-xs font-bold text-grey-darker italic">This example has been generated automatically.</h6> | ||
{% endif %} | ||
</div> | ||
</form> | ||
|
||
{% endmacro %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<div class="center-block p-8"> | ||
<a name="introduction"></a> | ||
<h1>{{asyncapi.info().title()}} {{asyncapi.info().version()}}</h1> | ||
<div class="leading-normal mb-4"> | ||
{% if asyncapi.info().termsOfService() %} | ||
<a class="border border-solid border-purple-lighter hover:bg-purple-lighter hover:text-purple-dark font-bold no-underline text-purple text-xs uppercase rounded mr-2 px-3 py-1" | ||
href="{{asyncapi.info().termsOfService()}}" target="_blank">Terms of Service</a> | ||
{% endif %} | ||
{% if asyncapi.info().license() %} | ||
<a class="border border-solid border-orange-lighter hover:bg-orange-lighter hover:text-orange-dark font-bold no-underline text-orange text-xs uppercase rounded mr-2 px-3 py-1" | ||
href="{{asyncapi.info().license().url()}}" target="_blank">{{asyncapi.info().license().name()}}</a> | ||
{% endif %} | ||
</div> | ||
|
||
<div class="markdown"> | ||
{{ asyncapi.info().description() | markdown2html | safe }} | ||
</div> | ||
|
||
|
||
<div class="leading-normal mb-4"> | ||
{% if asyncapi.info().contact() %} | ||
{% if asyncapi.info().contact().url() %} | ||
Contact link: <a class="border border-solid border-purple-lighter hover:bg-purple-lighter hover:text-purple-dark font-bold no-underline text-purple text-xs uppercase rounded mr-2 px-3 py-1" | ||
href="{{asyncapi.info().contact().url()}}" target="_blank">{%- if asyncapi.info().contact().name() %}{{asyncapi.info().contact().name()}}{%- else %}{{asyncapi.info().contact().url()}}{%- endif %}</a> | ||
{% endif %} | ||
{% if asyncapi.info().contact().email() %} | ||
Contact email: <a class="border border-solid border-purple-lighter hover:bg-purple-lighter hover:text-purple-dark font-bold no-underline text-purple text-xs uppercase rounded mr-2 px-3 py-1" | ||
href="{{asyncapi.info().contact().email()}}" target="_blank">{{asyncapi.info().contact().email()}}</a> | ||
{% endif %} | ||
{% endif %} | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{% from "./schema.html" import schema %} | ||
|
||
{% macro message(msg, showIndex=false, index=0, open=false) %} | ||
|
||
<div class="bg-grey-lighter rounded p-4 mt-2"> | ||
<div class="text-sm text-grey-darker mb-2"> | ||
{% if showIndex %} | ||
<span class="text-grey-darker font-bold mr-2">#{{index}}</span> | ||
{% endif %} | ||
{% if msg.title() %} | ||
{{msg.title()}} | ||
{% if msg.name() %} | ||
<span class="border text-orange rounded text-xs ml-3 py-0 px-2">{{msg.name()}}</span> | ||
{% endif %} | ||
{% else %} | ||
{% if msg.name() %} | ||
<span class="border text-orange rounded text-s py-0 px-2">{{msg.name()}}</span> | ||
{% endif %} | ||
{% endif %} | ||
</div> | ||
<p class="text-grey-dark text-sm">{{msg.summary()}}</p> | ||
<div class="mt-4 mb-4 markdown">{{ msg.description() | markdown2html | safe }}</div> | ||
{{ schema(msg.payload(), 'Payload', open=open) }} | ||
{% if msg.headers() %} | ||
<div class="mt-4"> | ||
{{ schema(msg.headers(), 'Headers', open=open) }} | ||
</div> | ||
{% endif %} | ||
</div> | ||
|
||
{% endmacro %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
{% from "./sliced-string.html" import slicedString %} | ||
{% from "./tags.html" import tags %} | ||
{% from "./message.html" import message %} | ||
{% from "./example.html" import example %} | ||
{% from "./schema-prop.html" import schemaProp %} | ||
|
||
|
||
{% macro operation(operation, operationType, channelName, channel) %} | ||
|
||
<a name="operation-{{operationType}}-{{channelName}}"></a> | ||
<div class="center-block p-8"> | ||
<div class="operation pt-8 pb-8"> | ||
<h3 class="font-mono text-base"> | ||
{% if operationType === 'publish' %} | ||
<span class="font-mono border border-blue text-blue uppercase p-1 rounded" title="Publish">Pub</span> | ||
{% endif %} | ||
{% if operationType === 'subscribe' %} | ||
<span class="font-mono border border-green-dark text-green-dark uppercase p-1 rounded" | ||
title="Subscribe">Sub</span> | ||
{% endif %} | ||
{{ slicedString(channelName) }} | ||
</h3> | ||
|
||
<div class="mt-4 mb-4 markdown">{{ channel.description() | markdown2html | safe }}</div> | ||
|
||
<p class="text-grey text-sm">{{operation.summary()}}</p> | ||
<div class="mt-4 mb-4 markdown">{{ operation.description() | markdown2html | safe }}</div> | ||
|
||
|
||
|
||
{% if channel.parameters() | length %} | ||
<div class="mt-2"> | ||
<div class="is-open"> | ||
<div class="js-prop cursor-pointer py-2 flex property"> | ||
<div class="pr-4" style="margin-top:-2px; min-width: 25%;"> | ||
<span class="text" style="word-break: break-word;">Parameters</span> | ||
<svg class="expand" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0"> | ||
<polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon> | ||
</svg> | ||
</div> | ||
</div> | ||
<div class="children bg-grey-lighter p-4 rounded"> | ||
<div class="bg-grey-lightest pl-8 pr-8 rounded"> | ||
{% for parameterName, parameter in channel.parameters() %} | ||
{{ schemaProp(parameter.schema(), parameterName, odd=false, specialName=false, required=true) }} | ||
{% endfor %} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
{% endif %} | ||
|
||
|
||
{% if operation.hasMultipleMessages() %} | ||
<p>Accepts <strong>one of</strong> the following messages:</p> | ||
{% for msg in operation.messages() %} | ||
{{ message(msg, showIndex=true, index=loop.index, open=false) }} | ||
{% endfor %} | ||
{% else %} | ||
<p>Accepts the following message:</p> | ||
{{ message(operation.message(0), showIndex=false, open=true) }} | ||
{% endif %} | ||
|
||
{{ tags(operation.tags()) }} | ||
</div> | ||
</div> | ||
|
||
<div class="right-block p-8"> | ||
<h4 class="text-lg text-white mb-4">Examples</h4> | ||
|
||
{% if operation.hasMultipleMessages() %} | ||
{% for msg in operation.messages() %} | ||
{{ example(msg, channelName) }} | ||
{% endfor %} | ||
{% else %} | ||
{{ example(operation.message(0), channelName) }} | ||
{% endif %} | ||
</div> | ||
|
||
|
||
{% endmacro %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{% from "./operation.html" import operation %} | ||
|
||
<a name="operations"></a> | ||
<h2 class="mb-4 ml-8">Operations</h2> | ||
|
||
{% for channelName, channel in asyncapi.channels() %} | ||
<div class="responsive-container"> | ||
{% if channel.hasPublish() %} | ||
{{ operation(channel.publish(), 'publish', channelName, channel) }} | ||
{% endif %} | ||
</div> | ||
<div class="responsive-container"> | ||
{% if channel.hasSubscribe() %} | ||
{{ operation(channel.subscribe(), 'subscribe', channelName, channel) }} | ||
{% endif %} | ||
</div> | ||
{% endfor %} |
Oops, something went wrong.