diff --git a/src/includer/generators/common.ts b/src/includer/generators/common.ts
index 5fdcfd5..2b718ab 100644
--- a/src/includer/generators/common.ts
+++ b/src/includer/generators/common.ts
@@ -48,6 +48,10 @@ function code(text: string) {
return EOL + ['```', text, '```'].join(EOL) + EOL;
}
+function method(text: string) {
+ return `${text.toUpperCase()} {.openapi__method}`
+}
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
function table(data: any[][]) {
const [names, ...rest] = data;
@@ -93,6 +97,6 @@ function anchor(ref: string) {
return link(ref, `#${slugify(ref).toLowerCase()}`);
}
-export {meta, list, link, title, body, mono, bold, table, code, cut, block, page, tabs, anchor};
+export {meta, list, link, title, body, mono, bold, table, code, cut, block, page, tabs, anchor, method};
-export default {meta, list, link, title, body, mono, bold, table, code, cut, block, tabs, anchor};
+export default {meta, list, link, title, body, mono, bold, table, code, cut, block, tabs, anchor, method};
diff --git a/src/includer/generators/endpoint.ts b/src/includer/generators/endpoint.ts
index ab49685..0b070c6 100644
--- a/src/includer/generators/endpoint.ts
+++ b/src/includer/generators/endpoint.ts
@@ -1,7 +1,7 @@
import {JSONSchema6} from 'json-schema';
import stringify from 'json-stringify-safe';
-import {meta, page, block, title, body, table, code, cut, tabs, bold} from './common';
+import {meta, page, block, title, body, table, code, cut, tabs, bold, method} from './common';
import {
INFO_TAB_NAME,
SANDBOX_TAB_NAME,
@@ -110,30 +110,36 @@ function sandbox({
}
function request(data: Endpoint) {
- const {path, method, servers} = data;
- const requestTableCols = ['method', 'url'];
+ const {path, method: type, servers} = data;
+ let description: string | undefined;
- const hrefs = block(servers.map(({url}) => code(url + '/' + path)));
+ const url = block(servers.map(({url}) => code(url + '/' + path)));
- const requestTableRow = [code(method.toUpperCase()), hrefs];
+ const requestTableRow = [method(type), `${url}`];
- if (servers.every((server: Server) => server.description)) {
- requestTableCols.push('description');
-
- const descriptions = block(servers.map(({description}) => code(description as string)));
- requestTableRow.push(descriptions);
+ if (servers.every((server: Server) => server.description)) {
+ description = block(servers.map(({description}) => description));
}
- const requestTable = table([
- requestTableCols,
- requestTableRow,
- ]);
+ const requestTable = block([
+ '
',
+ `
`,
+ ...requestTableRow,
+ '
',
+ '
'
+ ])
- return block([
+ const result = [
title(2)(REQUEST_SECTION_NAME),
requestTable,
- ]);
+ ]
+
+ if (description) {
+ result.push(`${description}{.openapi__request__description}`)
+ }
+
+ return block(result);
}
function parameters(allRefs: Refs, pagePrintedRefs: Set, params?: Parameters) {
@@ -195,7 +201,7 @@ function openapiBody(allRefs: Refs, pagePrintedRefs: Set, obj?: Schema)
const {type = 'schema', schema} = obj;
const sectionTitle = title(4)('Body');
- let result = [
+ let result: any[] = [
sectionTitle,
];
@@ -274,9 +280,11 @@ function response(allRefs: Refs, visited: Set, resp: Response) {
}
return block([
+ ``,
title(2)(header),
body(resp.description),
resp.schemas?.length && block(resp.schemas.map((s) => openapiBody(allRefs, visited, s))),
+ '
'
]);
}
diff --git a/src/includer/models.ts b/src/includer/models.ts
index 5a01317..342c8cd 100644
--- a/src/includer/models.ts
+++ b/src/includer/models.ts
@@ -156,7 +156,6 @@ export type Tag = {
export type Endpoints = Endpoint[];
-
export type Endpoint = {
id: string;
operationId?: string;
@@ -172,6 +171,7 @@ export type Endpoint = {
security: Security[];
noindex?: boolean;
hidden?: boolean;
+ deprecated?: boolean;
};
export type Specification = {
diff --git a/src/runtime/index.scss b/src/runtime/index.scss
index 0269f32..0881b7a 100644
--- a/src/runtime/index.scss
+++ b/src/runtime/index.scss
@@ -1,5 +1,108 @@
.openapi {
+ --dc-openapi-methods-post: rgba(50, 186, 118, 0.5);
+ --dc-openapi-methods-put: rgba(50, 186, 118, 0.3);
+ --dc-openapi-methods-get: rgba(54, 151, 241, 0.5);
+ --dc-openapi-methods-patch: rgba(255, 190, 92, 0.9);
+ --dc-openapi-methods-delete: rgba(255, 0, 61, 0.5);
+
+ --dc-openapi-status-code-ok: rgb(48, 170, 110);
+ --dc-openapi-status-code-redirect: rgb(52, 139, 220);
+ --dc-openapi-status-code-client: rgb(233, 3, 58);
+ --dc-openapi-status-code-server: rgb(255, 190, 92);
+
+ --dc-openapi-highlight: rgb(233, 174, 86);
+
&__required {
color: var(--yc-color-text-danger);
}
+
+ & #request {
+ margin-top: 0;
+ }
+
+ & .openapi__deprecated {
+ text-decoration: line-through;
+ }
+
+ & &__request {
+ display: flex;
+ align-items: center;
+ overflow-y: scroll;
+ width: 100%;
+
+ &__wrapper {
+ position: relative;
+ }
+
+ & * {
+ margin: 0;
+ }
+
+ & > .openapi__method {
+ background-color: var(--method);
+ padding: 8px 16px;
+ color: #fff;
+ border-radius: 5px 0 0 5px;
+ }
+
+ & > .yfm-clipboard {
+ border: 2px solid var(--method);
+ border-radius: 0 5px 5px 0;
+ white-space: nowrap;
+ overflow: visible;
+ position: initial;
+
+ code {
+ padding: 6px 20px 6px 6px;
+ }
+
+ pre, code {
+ border-radius: 0;
+ overflow: visible;
+ }
+
+ svg {
+ display: block;
+ opacity: 0;
+ transition: opacity 100ms;
+ position: absolute;
+ right: -8px;
+ top: 10px;
+ }
+
+ &:hover svg {
+ opacity: 1;
+ }
+ }
+
+ }
+
+ & h3 {
+ transition: color 100ms;
+
+ &.highlight {
+ color: var(--dc-openapi-highlight);
+ }
+ }
+
+ & .openapi__request__description {
+ margin: 20px 0 0 0;
+ font-size: 1.1em;
+ }
+
+ & h2[id^="2"] {
+ color: var(--dc-openapi-status-code-ok);
+ }
+
+ & h2[id^="3"] {
+ color: var(--dc-openapi-status-code-redirect);
+ }
+
+ & h2[id^="4"] {
+ color: var(--dc-openapi-status-code-client);
+ }
+
+ & h2[id^="5"] {
+ color: var(--dc-openapi-status-code-server);
+ }
}
diff --git a/src/runtime/index.tsx b/src/runtime/index.tsx
index 561ede0..315e864 100644
--- a/src/runtime/index.tsx
+++ b/src/runtime/index.tsx
@@ -1,14 +1,38 @@
-import React, {useEffect, useState} from 'react';
-import {createPortal} from 'react-dom';
-import {unescape} from 'html-escaper';
+import React, { useEffect, useState } from 'react';
+import { createPortal } from 'react-dom';
+import { unescape } from 'html-escaper';
-import {Sandbox} from './sandbox';
+import { Sandbox } from './sandbox';
import './index.scss';
export const Runtime: React.FC = () => {
const [sandbox, setSandbox] = useState(null);
+ useEffect(() => {
+ document.addEventListener('click', (event: any) => {
+ if (!event?.target?.closest('.openapi')) {
+ return;
+ }
+
+ const id = event?.target?.hash;
+
+ if (!id) {
+ return;
+ }
+
+ const anchor = document.querySelector(id);
+
+ if (anchor.classList.contains('highlight')) {
+ return;
+ }
+
+ anchor.classList.toggle('highlight');
+
+ setTimeout(() => anchor.classList.toggle('highlight'), 1_000)
+ })
+ }, []);
+
useEffect(() => {
setSandbox(document.querySelector('.yfm-sandbox-js'));
});
@@ -20,7 +44,7 @@ export const Runtime: React.FC = () => {
try {
const props = JSON.parse(unescape(sandbox.dataset.props));
- return createPortal(, sandbox);
+ return createPortal(, sandbox);
} catch (error) {
console.log(error);