diff --git a/demo/docusaurus.config.js b/demo/docusaurus.config.js index cf4acdfcb..ed13906bb 100644 --- a/demo/docusaurus.config.js +++ b/demo/docusaurus.config.js @@ -10,7 +10,7 @@ const config = { tagline: "OpenAPI plugin for generating API reference docs in Docusaurus v2.", url: "https://docusaurus-openapi.netlify.app", baseUrl: "/", - onBrokenLinks: "throw", + onBrokenLinks: "warn", onBrokenMarkdownLinks: "warn", favicon: "img/favicon.ico", organizationName: "cloud-annotations", // Usually your GitHub org/user name. @@ -68,7 +68,7 @@ const config = { /** @type {import('docusaurus-preset-openapi').ThemeConfig} */ ({ colorMode: { - disableSwitch: true, + disableSwitch: false, defaultMode: "dark", }, navbar: { diff --git a/demo/src/css/custom.css b/demo/src/css/custom.css index 6f50ce5e4..43bf70636 100644 --- a/demo/src/css/custom.css +++ b/demo/src/css/custom.css @@ -5,21 +5,157 @@ */ :root { - --ifm-code-font-size: 95%; -} + /* Primary Colors */ + --ifm-background-color: #ffffff; + --ifm-color-primary: #00c0e8; + --ifm-color-primary-dark: #00add1; + --ifm-color-primary-darker: #00a3c5; + --ifm-color-primary-darkest: #0086a2; + --ifm-color-primary-light: #00d3ff; + --ifm-color-primary-lighter: #0cd5ff; + --ifm-color-primary-lightest: #2fdbff; + /* Status Colors */ + --ifm-color-info: #00c0e8; + --ifm-color-success: #00cc66; + --ifm-color-warning: #ffcb06; + --ifm-color-danger: #fa582d; + /* Secondary Colors */ + --ifm-color-secondary: #768ba1; + --ifm-color-secondary-dark: #667d95; + --ifm-color-secondary-darker: #61768d; + --ifm-color-secondary-darkest: #4f6174; + --ifm-color-secondary-light: #8799ac; + --ifm-color-secondary-lighter: #8fa0b2; + --ifm-color-secondary-lightest: #a8b5c3; + --ifm-navbar-search-input-color: var(--ifm-color-gray-900); + --ifm-font-size-base: 95%; + --ifm-code-font-size: 90%; + --ifm-font-family-base: "Montserrat", sans-serif, "Font Awesome 5 Free"; + --ifm-font-family-monospace: "Roboto Mono", monospace; + --ifm-hero-color: #daf0f6; + --ifm-color-gray-switch: var(--ifm-color-gray-100); + /* Tables */ + /* --ifm-table-stripe-background: var(--ifm-background-color); */ + --ifm-table-border-width: 1px; + + --ifm-blockquote-background-color: var(--ifm-background-color); + --ifm-version-background: #ffffff; -html[data-theme="dark"] { - --ifm-color-primary: #58a6ff; - --ifm-background-color: #0d1117; - --ifm-navbar-background-color: #0d1117; - --ifm-color-emphasis-300: #30363d; - --ifm-card-background-color: #161b22; - --ifm-code-background: rgba(110, 118, 129, 0.4); --ifm-table-stripe-background: var(--ifm-table-background); --openapi-input-background: rgba(110, 118, 129, 0.4) !important; --openapi-monaco-border-color: #21262d !important; --openapi-monaco-background-color-dark: #0d1117 !important; - --ifm-dropdown-background-color: #161b22; + --openapi-code-green: var(--ifm-color-success) !important; + --openapi-code-blue: var(--ifm-color-primary) !important; + --openapi-code-red: var(--ifm-color-danger) !important; + --openapi-code-orange: var(--ifm-color-warning) !important; +} + +/* Dark mode overrides */ +html[data-theme="dark"] { + --ifm-color-emphasis-100: var(--ifm-color-gray-900); + --ifm-color-emphasis-200: var(--ifm-color-gray-800); + --ifm-color-emphasis-300: var(--ifm-color-gray-700); + --ifm-color-emphasis-400: var(--ifm-color-gray-600); + --ifm-color-emphasis-500: var(--ifm-color-gray-500); + --ifm-color-emphasis-600: var(--ifm-color-gray-400); + --ifm-color-emphasis-700: var(--ifm-color-gray-300); + --ifm-color-emphasis-800: var(--ifm-color-gray-200); + --ifm-color-emphasis-900: var(--ifm-color-gray-100); + + --ifm-background-color: #121212; + --ifm-background-surface-color: #1e2125; + + --ifm-color-content-secondary: rgba(255, 255, 255, 1); + + --ifm-heading-color: #ffffff !important; + + /* Mardown color in dark mode */ + --ifm-color-gray-800: var(--ifm-color-gray-300); + + --ifm-code-background: #393939 !important; + + --ifm-hero-color: var(--ifm-color-gray-600); + + --ifm-color-gray-switch: var(--ifm-color-gray-300); + + --ifm-blockquote-background-color: var(--ifm-background-color); + + --ifm-version-background: var(--ifm-background-color); + + --openapi-input-background: rgba(110, 118, 129, 0.4) !important; +} + +.footer--dark { + --ifm-footer-background-color: var(--ifm-color-gray-600); + color: white; +} + +.footer--dark a { + color: white; +} + +.footer--dark a:hover { + color: white; +} + +/* Tables */ + +/* .markdown table { + table-layout: fixed; + width: 100%; +} */ + +/* .markdown tr { + border-bottom: 1px solid var(--ifm-color-secondary) !important; +} */ + +/* .markdown td { + width: 25%; +} + +.markdown th { + text-align: left; +} */ + +/* Center all columns in main wrapper */ +.main-wrapper { + max-width: 1400px; + width: 1400px; + align-self: center; +} + +.main-wrapper h1[class^="docTitle"] { + font-size: 2.8rem; +} + +@media (max-width: 1416px) { + .main-wrapper { + max-width: 100%; + width: 100%; + } +} + +@media (max-width: 1320px) and (min-width: 997px) { + .container { + max-width: calc( + var(--ifm-container-width) - 125px - var(--ifm-spacing-horizontal) * 2 + ); + } +} + +/* Center navbar items */ +.navbar__inner { + max-width: 1360px; + margin: 0 auto; +} + +/* Force homepage to full width */ +.homepage { + width: 100%; + max-width: 100%; + max-height: 100%; + background-color: #303846; } .navbar__link:hover { @@ -42,9 +178,13 @@ html[data-theme="dark"] { font-size: 90%; } -.theme-api-markdown table { +/* .theme-api-markdown table { --ifm-code-background: #161b22; --ifm-table-border-color: #21262d; +} */ + +.theme-api-markdown td { + background-color: var(--ifm-alert-background-color); } .theme-api-markdown table table { @@ -57,6 +197,11 @@ html[data-theme="dark"] { -16px 0px 0px 0px var(--ifm-table-border-color); } +.theme-api-markdown .alert table { + box-shadow: -15px 0px 0px 0px var(--ifm-alert-background-color), + -16px 0px 0px 0px var(--ifm-alert-border-color); +} + .theme-api-markdown table table tr:first-child { border-top: 0; } @@ -131,7 +276,8 @@ html[data-theme="dark"] { } .api-code-tab--active { - background-color: transparent !important; + background: var(--ifm-color-primary); + /* color: white !important; */ border-bottom: 3px solid var(--ifm-color-primary) !important; border-bottom-color: var(--ifm-tabs-color-active-border) !important; border-bottom-left-radius: 0 !important; @@ -192,3 +338,76 @@ html[data-theme="dark"] .header-github-link:before { .footer__logo { margin-top: 0; } + +/* Sidebar Method labels */ +.api-method > .menu__link { + align-items: center; + justify-content: start; +} + +.api-method > .menu__link::before { + width: 50px; + height: 20px; + font-size: 12px; + line-height: 20px; + text-transform: uppercase; + font-weight: 600; + border-radius: 0.25rem; + border: 1px solid; + margin-right: var(--ifm-spacing-horizontal); + text-align: center; + flex-shrink: 0; +} + +.get > .menu__link::before { + content: "get"; + border-color: var(--openapi-code-blue); + color: var(--openapi-code-blue); +} + +.put > .menu__link::before { + content: "put"; + border-color: var(--openapi-code-orange); + color: var(--openapi-code-orange); +} + +.post > .menu__link::before { + content: "post"; + border-color: var(--openapi-code-green); + color: var(--openapi-code-green); +} + +.delete > .menu__link::before { + content: "del"; + border-color: var(--openapi-code-red); + color: var(--openapi-code-red); +} + +.patch > .menu__link::before { + content: "patch"; + border-color: var(--openapi-code-orange); + color: var(--openapi-code-orange); +} + +.alert--success { + --ifm-alert-background-color: var(--ifm-color-success-contrast-background); + --ifm-alert-background-color-highlight: rgba(0, 164, 0, 0.15); + --ifm-alert-foreground-color: var(--ifm-color-success-contrast-foreground); + --ifm-alert-border-color: var(--ifm-color-success-dark); +} + +.prism-code { + counter-reset: line-number; +} + +.prism-code .token-line::marker { + color: var(--ifm-color-gray-700); + content: counter(line-number); +} + +.prism-code .token-line { + counter-increment: line-number; + display: list-item; + padding-left: var(--ifm-pre-padding); + margin-left: var(--ifm-global-spacing); +} diff --git a/packages/docusaurus-plugin-openapi/src/markdown/createDetails.ts b/packages/docusaurus-plugin-openapi/src/markdown/createDetails.ts new file mode 100644 index 000000000..719134347 --- /dev/null +++ b/packages/docusaurus-plugin-openapi/src/markdown/createDetails.ts @@ -0,0 +1,16 @@ +/* ============================================================================ + * Copyright (c) Cloud Annotations + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * ========================================================================== */ + +import { create, Props } from "./utils"; + +export function createDetails({ children, style, ...rest }: Props) { + return create("details", { + style: { ...style }, + ...rest, + children, + }); +} diff --git a/packages/docusaurus-plugin-openapi/src/markdown/createDetailsSummary.ts b/packages/docusaurus-plugin-openapi/src/markdown/createDetailsSummary.ts new file mode 100644 index 000000000..86cf1a33e --- /dev/null +++ b/packages/docusaurus-plugin-openapi/src/markdown/createDetailsSummary.ts @@ -0,0 +1,16 @@ +/* ============================================================================ + * Copyright (c) Cloud Annotations + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * ========================================================================== */ + +import { create, Props } from "./utils"; + +export function createDetailsSummary({ children, style, ...rest }: Props) { + return create("summary", { + style: { ...style }, + ...rest, + children, + }); +} diff --git a/packages/docusaurus-plugin-openapi/src/markdown/createStatusCodes.ts b/packages/docusaurus-plugin-openapi/src/markdown/createStatusCodes.ts new file mode 100644 index 000000000..d8f13fc1d --- /dev/null +++ b/packages/docusaurus-plugin-openapi/src/markdown/createStatusCodes.ts @@ -0,0 +1,142 @@ +/* ============================================================================ + * Copyright (c) Cloud Annotations + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * ========================================================================== */ + +import { ApiItem } from "../types"; +import { createDescription } from "./createDescription"; +import { createSchemaTable } from "./createSchemaTable"; +import { createDetails } from "./createDetails"; +import { createDetailsSummary } from "./createDetailsSummary"; +import { create } from "./utils"; + +interface Props { + responses: ApiItem["responses"]; +} + +export function createStatusCodes({ responses }: Props) { + if (responses === undefined) { + return undefined; + } + + const codes = Object.keys(responses); + if (codes.length === 0) { + return undefined; + } + + type statusCodeOptions = { + [key: number]: string; + }; + + const statusCodes: statusCodeOptions = { + 100: "100 Continue", + 101: "101 Switching Protocols", + 103: "103 Early Hints", + 200: "200 OK", + 201: "201 Created", + 202: "202 Accepted", + 203: "203 Non-Authoritative Information", + 204: "204 No Content", + 205: "205 Reset Content", + 206: "206 Partial Content", + 300: "300 Multiple Choices", + 301: "301 Moved Permanently", + 302: "302 Found", + 303: "303 See Other", + 304: "304 Not Modified", + 307: "307 Temporary Redirect", + 308: "308 Permanent Redirect", + 400: "400 Bad Request", + 401: "401 Unauthorized", + 402: "402 Payment Required", + 403: "403 Forbidden", + 404: "404 Not Found", + 405: "405 Method Not Allowed", + 406: "406 Not Acceptable", + 407: "407 Proxy Authentication Required", + 408: "408 Request Timeout", + 409: "409 Conflict", + 410: "410 Gone", + 411: "411 Length Required", + 412: "412 Precondition Failed", + 413: "413 Payload Too Large", + 414: "414 URI Too Long", + 415: "415 Unsupported Media Type", + 416: "416 Range Not Satisfiable", + 417: "417 Expectation Failed", + 418: "418 I'm a teapot", + 422: "422 Unprocessable Entity", + 425: "425 Too Early", + 426: "426 Upgrade Required", + 428: "428 Precondition Required", + 429: "429 Too Many Requests", + 431: "431 Request Header Fields Too Large", + 451: "451 Unavailable For Legal Reasons", + 500: "500 Internal Server Error", + 501: "501 Not Implemented", + 502: "502 Bad Gateway", + 503: "503 Service Unavailable", + 504: "504 Gateway Timeout", + 505: "505 HTTP Version Not Supported", + 506: "506 Variant Also Negotiates", + 507: "507 Insufficient Storage", + 508: "508 Loop Detected", + 510: "510 Not Extended", + 511: "511 Network Authentication Required", + }; + + return create("div", { + children: [ + create("p", { + children: "Responses", + style: { + fontWeight: "var(--ifm-table-head-font-weight)", + }, + }), + create("div", { + children: codes.map((code) => + create("div", { + children: [ + createDetails({ + className: + parseInt(code) >= 400 + ? "alert--danger" + : parseInt(code) >= 200 && parseInt(code) < 300 + ? "alert--success" + : "alert--warning", + children: [ + createDetailsSummary({ + children: create("span", { + children: [ + create("div", { + children: statusCodes[code as any], + }), + ], + }), + }), + create("div", { + children: createDescription(responses[code].description), + }), + create("div", { + children: createSchemaTable({ + style: { + marginTop: "var(--ifm-table-cell-padding)", + marginBottom: "0px", + }, + title: "Schema", + body: { + content: responses[code].content, + }, + }), + }), + ], + }), + ], + }) + ), + }), + ], + }); +} diff --git a/packages/docusaurus-plugin-openapi/src/markdown/createStatusCodesTable.ts b/packages/docusaurus-plugin-openapi/src/markdown/createStatusCodesTable.ts deleted file mode 100644 index e39732f93..000000000 --- a/packages/docusaurus-plugin-openapi/src/markdown/createStatusCodesTable.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* ============================================================================ - * Copyright (c) Cloud Annotations - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * ========================================================================== */ - -import { ApiItem } from "../types"; -import { createDescription } from "./createDescription"; -import { createFullWidthTable } from "./createFullWidthTable"; -import { createSchemaTable } from "./createSchemaTable"; -import { create } from "./utils"; - -interface Props { - responses: ApiItem["responses"]; -} - -export function createStatusCodesTable({ responses }: Props) { - if (responses === undefined) { - return undefined; - } - - const codes = Object.keys(responses); - if (codes.length === 0) { - return undefined; - } - - return createFullWidthTable({ - children: [ - create("thead", { - children: create("tr", { - children: create("th", { - style: { textAlign: "left" }, - children: `Responses`, - }), - }), - }), - create("tbody", { - children: codes.map((code) => - create("tr", { - children: create("td", { - children: [ - create("div", { - style: { display: "flex" }, - children: [ - create("div", { - style: { marginRight: "var(--ifm-table-cell-padding)" }, - children: create("code", { - children: code, - }), - }), - create("div", { - children: createDescription(responses[code].description), - }), - ], - }), - create("div", { - children: createSchemaTable({ - style: { - marginTop: "var(--ifm-table-cell-padding)", - marginBottom: "0px", - }, - title: "Schema", - body: { - content: responses[code].content, - }, - }), - }), - ], - }), - }) - ), - }), - ], - }); -} diff --git a/packages/docusaurus-plugin-openapi/src/markdown/index.ts b/packages/docusaurus-plugin-openapi/src/markdown/index.ts index ba1f6f39f..ff774bc5d 100644 --- a/packages/docusaurus-plugin-openapi/src/markdown/index.ts +++ b/packages/docusaurus-plugin-openapi/src/markdown/index.ts @@ -12,7 +12,7 @@ import { createDeprecationNotice } from "./createDeprecationNotice"; import { createDescription } from "./createDescription"; import { createParamsTable } from "./createParamsTable"; import { createRequestBodyTable } from "./createRequestBodyTable"; -import { createStatusCodesTable } from "./createStatusCodesTable"; +import { createStatusCodes } from "./createStatusCodes"; import { createVersionBadge } from "./createVersionBadge"; import { render } from "./utils"; @@ -36,7 +36,7 @@ export function createApiPageMD({ createParamsTable({ parameters, type: "header" }), createParamsTable({ parameters, type: "cookie" }), createRequestBodyTable({ title: "Request Body", body: requestBody }), - createStatusCodesTable({ responses }), + createStatusCodes({ responses }), ]); }