Skip to content

Commit

Permalink
feat: render missed parts of info and tag objects (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
magicmatatjahu authored Oct 11, 2021
1 parent 40c7bd6 commit 1e765d2
Show file tree
Hide file tree
Showing 9 changed files with 460 additions and 50 deletions.
121 changes: 102 additions & 19 deletions components/Info.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,121 @@
import { Text } from "@asyncapi/generator-react-sdk";

import { Header, Link, Image } from "./common";
import { Tags } from "./Tags";
import { Header, Link, Image, List } from "./common";

export function Info({ asyncapi, params }) {
export function Info({ asyncapi, params = {} }) {
const info = asyncapi.info();

const specId = asyncapi.id();
const externalDocs = asyncapi.externalDocs();
const license = info.license();
const termsOfService = info.termsOfService();
const defaultContentType = asyncapi.defaultContentType();
const contact = info.contact();

const infoList = [];
if (specId) {
infoList.push(`Specification ID: \`${specId}\``);
}
if (license) {
infoList.push(license.url() ? (
<>
License:{' '}
<Link
href={license.url()}
>
{license.name()}
</Link>
</>
) : `License: ${license.name()}`);
}
if (termsOfService) {
infoList.push(
<>
Terms of service:{' '}
<Link
href={termsOfService}
>
{termsOfService}
</Link>
</>
);
}
if (defaultContentType) {
infoList.push(
<>
Default content type:{' '}
<Link
href={`https://www.iana.org/assignments/media-types/${defaultContentType}`}
>
{defaultContentType}
</Link>
</>
);
}
if (contact) {
contact.url() && infoList.push(
<>
Support:{' '}
<Link
href={contact.url()}
>
{contact.name() || 'Link'}
</Link>
</>
);
contact.email() && infoList.push(
<>
Email support:{' '}
<Link
href={`mailto:${contact.email()}`}
>
{contact.email()}
</Link>
</>
);
}

return (
<>
<Text>
<Header type={1}>
{info.title()} {params.version || info.version()} documentation
</Header>

{info.description() && (
{info.hasExt('x-logo') && (
<Text>
<Image src={info.ext('x-logo')} desc={`${info.title()} logo`} />
</Text>
)}

{infoList.length && (
<>
<List list={infoList} />
<Text />
</>
)}

{externalDocs && (
<Text newLines={2}>
<Link
href={externalDocs.url()}
>
{externalDocs.hasDescription() ? externalDocs.description() : 'Find more info here.'}
</Link>
</Text>
)}

{info.hasDescription() && (
<Text>
{info.description()}
</Text>
)}

{info.hasExt('x-logo') && (
{asyncapi.hasTags() && (
<Text>
<Image src={info.ext('x-logo')} desc={`${info.title()} logo`} />
<Tags tags={asyncapi.tags()} />
</Text>
)}
</>
</Text>
);
}

export function TermsOfService({ asyncapi }) {
const termsOfService = asyncapi.info().termsOfService();
return termsOfService ? (
<Text newLines={2}>
<Header type={2}>
Terms of service
</Header>
<Link href={termsOfService}>{termsOfService}</Link>
</Text>
) : null;
}
3 changes: 2 additions & 1 deletion components/Message.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Text } from "@asyncapi/generator-react-sdk";
import { generateExample, getPayloadExamples, getHeadersExamples } from "@asyncapi/generator-filters";

import { Header, CodeBlock, BlockQuote, Tags } from "./common";
import { Schema } from "./Schema";
import { Tags } from "./Tags";
import { Header, CodeBlock, BlockQuote } from "./common";

export function Message({ message, title = 'Message' }) {
return (
Expand Down
85 changes: 85 additions & 0 deletions components/TableOfContents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Text, Indent, IndentationTypes } from "@asyncapi/generator-react-sdk";

import { Header, Link, ListItem } from "../components/common";

export function TableOfContents({ asyncapi }) {
const serversList = Object.keys(asyncapi.servers()).map(serverName => {
return (
<Indent size={2} type={IndentationTypes.SPACES} key={serverName}>
<ListItem>
<Link href={`#${slugify(serverName)}-server`}>{serverName}</Link>
</ListItem>
</Indent>
);
});
const channelsList = Object.keys(asyncapi.channels()).map(channelName => {
return (
<Indent size={2} type={IndentationTypes.SPACES} key={channelName}>
<ListItem>
<Link href={`#${slugify(channelName)}-channel`}>{channelName}</Link>
</ListItem>
</Indent>
);
});

return (
<>
<Header type={2}>Table of Contents</Header>
<Text>
{asyncapi.hasServers() &&
<ListItem>
<Link href="#servers">Servers</Link>
</ListItem>
}
{serversList.length > 0 && serversList}
{asyncapi.hasChannels() &&
<ListItem>
<Link href="#channels">Channels</Link>
</ListItem>
}
{channelsList.length > 0 && channelsList}
</Text>
</>
);
}

/**
* Slugify (change value to appropriate hash) the url part of a markdown link.
*
* @param {String} `str` The string to slugify
* @return {String}
*/
function slugify(str) {
str = getTitle(str);
str = str.toLowerCase();

// `split(...).join(...)` is faster than `replace(..., ...)`
// for spaces
str = str.split(' ').join('-');
// for tabs
str = str.split(/\t/).join('--');
// for html tags
str = str.split(/<\/?[^>]{1,100}>/).join('');
// for special characters from ASCII (part 1)
str = str.split(/[|$&`~=\\\/@+*!?({[\]})<>.,;:'"^]/).join('');
// for special characters from ASCII (part 2)
str = str.split(/[ ]/).join('');

return str;
}

/**
* Get the "title" from a markdown link
*
* @param {String} `str` The string to retrieve title
* @return {String}
*/
function getTitle(str) {
// check if in `str` is "title" from a markdown link (use `(` char at the end for easy markdown link checking)
if (/^\[[^\]]+\]\(/.test(str)) {
// retrieve "title" from a markdown link
var m = /^\[([^\]]+)\]/.exec(str);
if (m) return m[1];
}
return str;
}
44 changes: 44 additions & 0 deletions components/Tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { IndentationTypes, Text } from "@asyncapi/generator-react-sdk";

import { ListItem, Link } from "./common";

export function Tags({ tags = [] }) {
if (tags.length === 0) {
return null
}

return (
<>
{tags.map(tag => (
<Tag tag={tag} key={tag.name()} />
))}
</>
);
}

function Tag({ tag }) {
const description = tag.description();
const externalDocs = tag.externalDocs();

return (
<>
<Text>
<ListItem>{tag.name()}</ListItem>
</Text>
{description && (
<Text indent={2} type={IndentationTypes.SPACES}>
{description}
</Text>
)}
{externalDocs && (
<Text indent={2} type={IndentationTypes.SPACES}>
<Link
href={externalDocs.url()}
>
{externalDocs.hasDescription() ? externalDocs.description() : 'Find more info here.'}
</Link>
</Text>
)}
</>
);
}
7 changes: 7 additions & 0 deletions components/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ export function Image({ src = "", desc = "", childrenContent = "" }) {
return `![${desc || childrenContent}](${src})`;
}

export function List({ list = [] }) {
if (list.length === 0) return null;
return list.map(item => (
<ListItem>{item}</ListItem>
));
}

export function ListItem({ type = "*", childrenContent = "" }) {
return <Text>{`${type} ${childrenContent}`}</Text>;
}
Expand Down
35 changes: 5 additions & 30 deletions template/asyncapi.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,20 @@
import { File, Text } from "@asyncapi/generator-react-sdk";
import { File } from "@asyncapi/generator-react-sdk";

import { Header, Link, ListItem } from "../components/common";
import { Info, TermsOfService } from "../components/Info";
import { Info } from "../components/Info";
import { Servers } from "../components/Servers";
import { Channels } from "../components/Channels";
import { FrontMatter } from "../components/FrontMatter";
import { TableOfContents } from "../components/TableOfContents";

export default function({ asyncapi, params }) {
export default function({ asyncapi, params = {} }) {
return (
<File name={params.outFilename || 'asyncapi.md'}>
{params.frontMatter && <FrontMatter asyncapi={asyncapi} params={params} />}
<Info asyncapi={asyncapi} params={params} />
{params.toc !== 'false' && <TableOfContents asyncapi={asyncapi} />}
<TermsOfService asyncapi={asyncapi} />

<Servers asyncapi={asyncapi} />
<Channels asyncapi={asyncapi} />
</File>
);
}

function TableOfContents({ asyncapi }) {
return (
<>
<Header type={2}>Table of Contents</Header>
<Text>
{asyncapi.info().termsOfService() &&
<ListItem>
<Link href="#terms-of-service">Terms of Service</Link>
</ListItem>
}
{asyncapi.hasServers() &&
<ListItem>
<Link href="#servers">Servers</Link>
</ListItem>
}
{asyncapi.hasChannels() &&
<ListItem>
<Link href="#channels">Channels</Link>
</ListItem>
}
</Text>
</>
);
}
Loading

0 comments on commit 1e765d2

Please sign in to comment.