From 7e7a96e2105eea5b2d28d441bf8d4c904d93844eac87090fc61cd2311de66d86 Mon Sep 17 00:00:00 2001 From: Nick Slowinski Date: Mon, 27 May 2024 06:22:54 +0200 Subject: [PATCH] Add server-2024-05-01 Signed-off-by: Nick Slowinski --- babel.config.cjs | 3 + blog/2023-07-03-new-frontend.md | 21 ++ blog/2023-07-29-tag-filter.md | 19 ++ blog/2023-11-29-simpleicons10.md | 14 + blog/2024-01-13-simpleicons11.md | 21 ++ categories/.gitkeep | 0 docs/index.md | 13 + docs/logos.md | 37 +++ docs/static-badges.md | 13 + docusaurus.config.cjs | 134 +++++++++ package.json | 16 ++ sidebars.cjs | 31 ++ src/components/homepage-features.js | 108 +++++++ src/components/homepage-features.module.css | 11 + src/css/custom.css | 52 ++++ src/pages/community.md | 67 +++++ src/pages/index.js | 39 +++ src/pages/index.module.css | 23 ++ src/plugins/strip-code-block-links.js | 30 ++ src/theme/ApiDemoPanel/Curl/index.js | 300 ++++++++++++++++++++ src/theme/ApiDemoPanel/Response/index.js | 66 +++++ src/theme/DocPaginator/index.js | 3 + static/.nojekyll | 0 static/img/builder.png | Bin 0 -> 31273 bytes static/img/favicon.ico | Bin 0 -> 15086 bytes static/img/logo.png | Bin 0 -> 16615 bytes 26 files changed, 1021 insertions(+) create mode 100644 babel.config.cjs create mode 100644 blog/2023-07-03-new-frontend.md create mode 100644 blog/2023-07-29-tag-filter.md create mode 100644 blog/2023-11-29-simpleicons10.md create mode 100644 blog/2024-01-13-simpleicons11.md create mode 100644 categories/.gitkeep create mode 100644 docs/index.md create mode 100644 docs/logos.md create mode 100644 docs/static-badges.md create mode 100644 docusaurus.config.cjs create mode 100644 package.json create mode 100644 sidebars.cjs create mode 100644 src/components/homepage-features.js create mode 100644 src/components/homepage-features.module.css create mode 100644 src/css/custom.css create mode 100644 src/pages/community.md create mode 100644 src/pages/index.js create mode 100644 src/pages/index.module.css create mode 100644 src/plugins/strip-code-block-links.js create mode 100644 src/theme/ApiDemoPanel/Curl/index.js create mode 100644 src/theme/ApiDemoPanel/Response/index.js create mode 100644 src/theme/DocPaginator/index.js create mode 100644 static/.nojekyll create mode 100644 static/img/builder.png create mode 100644 static/img/favicon.ico create mode 100644 static/img/logo.png diff --git a/babel.config.cjs b/babel.config.cjs new file mode 100644 index 0000000..47fe5c9 --- /dev/null +++ b/babel.config.cjs @@ -0,0 +1,3 @@ +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +} diff --git a/blog/2023-07-03-new-frontend.md b/blog/2023-07-03-new-frontend.md new file mode 100644 index 0000000..cb19c30 --- /dev/null +++ b/blog/2023-07-03-new-frontend.md @@ -0,0 +1,21 @@ +--- +slug: new-frontend +title: We launched a new frontend +authors: + name: chris48s + title: Shields.io Core Team + url: https://github.com/chris48s + image_url: https://avatars.githubusercontent.com/u/6025893 +tags: [] +--- + +Alongside the general visual refresh and improvements to look and feel, our new frontend has allowed us to address a number of long-standing feature requests and enhancements: + +- Clearer and more discoverable documentation for our [static](https://shields.io/badges/static-badge), dynamic [json](https://shields.io/badges/dynamic-json-badge)/[xml](https://shields.io/badges/dynamic-xml-badge)/[yaml](https://shields.io/badges/dynamic-yaml-badge) and [endpoint](https://shields.io/badges/endpoint-badge) badges +- Improved badge builder interface, with all optional query parameters included in the builder for each badge +- Each badge now has its own documentation page, which we can link to. e.g: [https://shields.io/badges/discord](https://shields.io/badges/discord) +- Light/dark mode themes +- Improved search +- Documentation for individual path and query parameters + +The new site also comes with big maintenance benefits for the core team. We rely heavily on [docusaurus](https://docusaurus.io/), [docusaurus-openapi](https://github.com/cloud-annotations/docusaurus-openapi), and [docusaurus-search-local](https://github.com/easyops-cn/docusaurus-search-local). This moves us to a mostly declarative setup, massively reducing the amount of custom frontend code we maintain ourselves. diff --git a/blog/2023-07-29-tag-filter.md b/blog/2023-07-29-tag-filter.md new file mode 100644 index 0000000..88abd32 --- /dev/null +++ b/blog/2023-07-29-tag-filter.md @@ -0,0 +1,19 @@ +--- +slug: tag-filter +title: Applying filters to GitHub Tag and Release badges +authors: + name: chris48s + title: Shields.io Core Team + url: https://github.com/chris48s + image_url: https://avatars.githubusercontent.com/u/6025893 +tags: [] +--- + +We recently shipped a feature which allows you to pass an arbitrary filter to the GitHub tag and release badges. The `filter` param can be used to apply a filter to the project's tag or release names before selecting the latest from the list. Two constructs are available: `*` is a wildcard matching zero or more characters, and if the pattern starts with a `!`, the whole pattern is negated. + +To give an example of how this might be useful, we create two types of tags on our GitHub repo: https://github.com/badges/shields/tags There are tags in the format `major.minor.patch` which correspond to our [NPM package releases](https://www.npmjs.com/package/badge-maker?activeTab=versions) and tags in the format `server-YYYY-MM-DD` that correspond to our [docker snapshot releases](https://registry.hub.docker.com/r/shieldsio/shields/tags?page=1&ordering=last_updated). + +In our case, this would allow us to make a badge that applies the filter `!server-*` to filter out the snapshot tags and just select the latest package tag. + +- ![tag badge without filter](https://img.shields.io/github/v/tag/badges/shields) - https://img.shields.io/github/v/tag/badges/shields +- ![tag badge with filter](https://img.shields.io/github/v/tag/badges/shields?filter=%21server-%2A) - https://img.shields.io/github/v/tag/badges/shields?filter=%21server-%2A diff --git a/blog/2023-11-29-simpleicons10.md b/blog/2023-11-29-simpleicons10.md new file mode 100644 index 0000000..2d49227 --- /dev/null +++ b/blog/2023-11-29-simpleicons10.md @@ -0,0 +1,14 @@ +--- +slug: simple-icons-10 +title: Simple Icons 10 +authors: + name: chris48s + title: Shields.io Core Team + url: https://github.com/chris48s + image_url: https://avatars.githubusercontent.com/u/6025893 +tags: [] +--- + +Logos on Shields.io are provided by SimpleIcons. We've recently upgraded to SimpleIcons 10. This release removes 45 icons. A full list of the removals can be found in the [release notes](https://github.com/simple-icons/simple-icons/releases/tag/10.0.0). + +Please remember that we are just consumers of SimpleIcons. Decisions about changes and removals are made by the [SimpleIcons](https://github.com/simple-icons/simple-icons) project. diff --git a/blog/2024-01-13-simpleicons11.md b/blog/2024-01-13-simpleicons11.md new file mode 100644 index 0000000..08daadc --- /dev/null +++ b/blog/2024-01-13-simpleicons11.md @@ -0,0 +1,21 @@ +--- +slug: simple-icons-11 +title: Simple Icons 11 +authors: + name: chris48s + title: Shields.io Core Team + url: https://github.com/chris48s + image_url: https://avatars.githubusercontent.com/u/6025893 +tags: [] +--- + +Logos on Shields.io are provided by SimpleIcons. We've recently upgraded to SimpleIcons 11. This release removes the following 4 icons: + +- Babylon.js +- Hulu +- Pepsi +- Uno + +More details can be found in the [release notes](https://github.com/simple-icons/simple-icons/releases/tag/11.0.0). + +Please remember that we are just consumers of SimpleIcons. Decisions about changes and removals are made by the [SimpleIcons](https://github.com/simple-icons/simple-icons) project. diff --git a/categories/.gitkeep b/categories/.gitkeep new file mode 100644 index 0000000..473a0f4 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..3f6c657 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,13 @@ +--- +sidebar_position: 1 +--- + +# Intro + +Shields.io is a service for concise, consistent, and legible badges, which can easily be included in GitHub readmes or any other web page. The service supports dozens of continuous integration services, package registries, distributions, app stores, social networks, code coverage services, and code analysis services. It is used by some of the world's most popular open-source projects. + +Browse a [complete list of badges](/badges) and locate a particular badge by using the search bar or by browsing the categories. + +Use the builder to fill in required path parameters for that badge type (like your username or repo) and optionally customize (label, colors etc.). And it's ready for use! Copy your badge url or code snippet, which can then be added to places like your GitHub readme files or other web pages. + +![screenshot of the badge builder](/img/builder.png) diff --git a/docs/logos.md b/docs/logos.md new file mode 100644 index 0000000..4df5400 --- /dev/null +++ b/docs/logos.md @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +# Logos + +## SimpleIcons + +We support a wide range of logos via [SimpleIcons](https://simpleicons.org/). All simple-icons are referenced using icon slugs. e.g: + +![](https://img.shields.io/npm/v/npm.svg?logo=nodedotjs) - https://img.shields.io/npm/v/npm.svg?logo=nodedotjs + +You can click the icon title on simple-icons to copy the slug or they can be found in the slugs.md file in the simple-icons repository. NB - the Simple Icons site and slugs.md page may at times contain new icons that haven't yet been pulled into Shields.io yet. More information on how and when we incorporate icon updates can be found [here](https://github.com/badges/shields/discussions/5369). + +## Shields logos + +We also maintain a small number of custom logos for a handful of services: https://github.com/badges/shields/tree/master/logo They can also be referenced by name and take preference to SimpleIcons e.g: + +![](https://img.shields.io/npm/v/npm.svg?logo=npm) - https://img.shields.io/npm/v/npm.svg?logo=npm + +## Custom Logos + +Any custom logo can be passed in a URL parameter by base64 encoding it. e.g: + +![](https://img.shields.io/badge/play-station-blue.svg?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48cGF0aCBkPSJNMTI5IDExMWMtNTUgNC05MyA2Ni05MyA3OEwwIDM5OGMtMiA3MCAzNiA5MiA2OSA5MWgxYzc5IDAgODctNTcgMTMwLTEyOGgyMDFjNDMgNzEgNTAgMTI4IDEyOSAxMjhoMWMzMyAxIDcxLTIxIDY5LTkxbC0zNi0yMDljMC0xMi00MC03OC05OC03OGgtMTBjLTYzIDAtOTIgMzUtOTIgNDJIMjM2YzAtNy0yOS00Mi05Mi00MmgtMTV6IiBmaWxsPSIjZmZmIi8+PC9zdmc+) - https://img.shields.io/badge/play-station-blue.svg?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48cGF0aCBkPSJNMTI5IDExMWMtNTUgNC05MyA2Ni05MyA3OEwwIDM5OGMtMiA3MCAzNiA5MiA2OSA5MWgxYzc5IDAgODctNTcgMTMwLTEyOGgyMDFjNDMgNzEgNTAgMTI4IDEyOSAxMjhoMWMzMyAxIDcxLTIxIDY5LTkxbC0zNi0yMDljMC0xMi00MC03OC05OC03OGgtMTBjLTYzIDAtOTIgMzUtOTIgNDJIMjM2YzAtNy0yOS00Mi05Mi00MmgtMTV6IiBmaWxsPSIjZmZmIi8+PC9zdmc+ + +## logoColor parameter + +The `logoColor` param can be used to set the color of the logo. Hex, rgb, rgba, hsl, hsla and css named colors can all be used. For SimpleIcons named logos (which are monochrome), the color will be applied to the SimpleIcons logo. + +- ![](https://img.shields.io/badge/logo-javascript-blue?logo=javascript) - https://img.shields.io/badge/logo-javascript-blue?logo=javascript +- ![](https://img.shields.io/badge/logo-javascript-blue?logo=javascript&logoColor=f5f5f5) - https://img.shields.io/badge/logo-javascript-blue?logo=javascript&logoColor=f5f5f5 + +In the case where Shields hosts a custom multi-colored logo, if the `logoColor` param is passed, the corresponding SimpleIcons logo will be substituted and colored. + +- ![](https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab) - https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab +- ![](https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab&logoColor=white) - https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab&logoColor=white diff --git a/docs/static-badges.md b/docs/static-badges.md new file mode 100644 index 0000000..583356f --- /dev/null +++ b/docs/static-badges.md @@ -0,0 +1,13 @@ +# Static Badges + +It is possible to use shields.io to make a wide variety of badges displaying static text and/or logos. For example: + +- ![any text you like](https://img.shields.io/badge/any%20text-you%20like-blue) - https://img.shields.io/badge/any%20text-you%20like-blue +- ![just the message](https://img.shields.io/badge/just%20the%20message-8A2BE2) - https://img.shields.io/badge/just%20the%20message-8A2BE2 +- !['for the badge' style](https://img.shields.io/badge/%27for%20the%20badge%27%20style-20B2AA?style=for-the-badge) - https://img.shields.io/badge/%27for%20the%20badge%27%20style-20B2AA?style=for-the-badge +- ![with a logo](https://img.shields.io/badge/with%20a%20logo-grey?style=for-the-badge&logo=javascript) - https://img.shields.io/badge/with%20a%20logo-grey?style=for-the-badge&logo=javascript + +For more info, see: + +- [Static badge builder](/badges/static-badge), including full documentation of styles and parameters +- [Logos](/docs/logos) diff --git a/docusaurus.config.cjs b/docusaurus.config.cjs new file mode 100644 index 0000000..b9b76e4 --- /dev/null +++ b/docusaurus.config.cjs @@ -0,0 +1,134 @@ +const lightCodeTheme = require('prism-react-renderer').themes.github +const darkCodeTheme = require('prism-react-renderer').themes.dracula +const stripCodeBlockLinks = require('./src/plugins/strip-code-block-links') + +/** @type {import('@docusaurus/types').Config} */ +const config = { + title: 'Shields.io', + tagline: 'Concise, consistent, and legible badges', + url: 'https://shields.io', + baseUrl: '/', + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'warn', + favicon: 'img/favicon.ico', + organizationName: 'badges', + projectName: 'shields', + + themes: [ + [ + require.resolve('@easyops-cn/docusaurus-search-local'), + /** @type {import("@easyops-cn/docusaurus-search-local").PluginOptions} */ + ({ + hashed: true, + indexPages: true, + }), + ], + ], + + markdown: { + mdx1Compat: { + comments: true, + admonitions: true, + headingIds: true, + }, + }, + + presets: [ + [ + 'docusaurus-preset-openapi', + /** @type {import('docusaurus-preset-openapi').Options} */ + ({ + docs: { + sidebarPath: require.resolve('./sidebars.cjs'), + editUrl: 'https://github.com/badges/shields/tree/master/frontend', + }, + blog: { + showReadingTime: true, + editUrl: 'https://github.com/badges/shields/tree/master/frontend', + }, + theme: { + customCss: require.resolve('./src/css/custom.css'), + }, + api: { + path: 'categories', + routeBasePath: 'badges', + rehypePlugins: [stripCodeBlockLinks], + }, + }), + ], + ], + + themeConfig: + /** @type {import('docusaurus-preset-openapi').ThemeConfig} */ + ({ + languageTabs: [], + navbar: { + title: 'Shields.io', + logo: { + alt: 'Shields Logo', + src: 'img/logo.png', + }, + items: [ + { to: '/badges', label: 'Badges', position: 'left' }, + { + to: '/docs', + label: 'Documentation', + position: 'left', + }, + { to: '/community', label: 'Community', position: 'left' }, + { to: '/blog', label: 'Blog', position: 'left' }, + { + href: 'https://github.com/badges/shields', + label: 'GitHub', + position: 'right', + }, + ], + }, + footer: { + style: 'dark', + links: [ + { + title: 'Community', + items: [ + { + label: 'GitHub', + href: 'https://github.com/badges/shields', + }, + { + label: 'Open Collective', + href: 'https://opencollective.com/shields', + }, + { + label: 'Discord', + href: 'https://discord.gg/HjJCwm5', + }, + { + label: 'Awesome Badges', + href: 'https://github.com/badges/awesome-badges', + }, + ], + }, + { + title: 'Stats', + items: [ + { + label: 'Service Status', + href: 'https://stats.uptimerobot.com/PjXogHB5p', + }, + { + label: 'Metrics dashboard', + href: 'https://metrics.shields.io/', + }, + ], + }, + ], + copyright: `Copyright © ${new Date().getFullYear()} Shields.io. Built with Docusaurus.`, + }, + prism: { + theme: lightCodeTheme, + darkTheme: darkCodeTheme, + }, + }), +} + +module.exports = config diff --git a/package.json b/package.json new file mode 100644 index 0000000..4f2b34c --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "badge-frontend", + "version": "0.0.0", + "description": "Shields.io frontend", + "private": true, + "homepage": "https://shields.io", + "license": "CC0-1.0", + "repository": { + "type": "git", + "url": "git+https://github.com/badges/shields.git", + "directory": "frontend" + }, + "scripts": { + "test": "echo 'Run tests from parent dir'; false" + } +} diff --git a/sidebars.cjs b/sidebars.cjs new file mode 100644 index 0000000..1d0254f --- /dev/null +++ b/sidebars.cjs @@ -0,0 +1,31 @@ +/** + * Creating a sidebar enables you to: + * - create an ordered group of docs + * - render a sidebar for each doc of that group + * - provide next/previous navigation + * + * The sidebars can be generated from the filesystem, or explicitly defined here. + * + * Create as many sidebars as you want. + */ + +// @ts-check + +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const sidebars = { + // By default, Docusaurus generates a sidebar from the docs folder structure + tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }], + + // But you can create a sidebar manually + /* + tutorialSidebar: [ + { + type: 'category', + label: 'Tutorial', + items: ['hello'], + }, + ], + */ +} + +module.exports = sidebars diff --git a/src/components/homepage-features.js b/src/components/homepage-features.js new file mode 100644 index 0000000..a320f1e --- /dev/null +++ b/src/components/homepage-features.js @@ -0,0 +1,108 @@ +import React from 'react' +import clsx from 'clsx' +import styles from './homepage-features.module.css' + +const FeatureList = [ + { + title: 'Dynamic badges', + description: ( + <> + build:passing +
+ Show metrics for your project. We've got badges for hundreds of + services. + + ), + }, + { + title: 'Static Badges', + description: ( + <> + Create a badge with +
+ any text you like + + ), + }, + { + title: 'Badge-Maker NPM library', + description: ( + <> + Render badges in your own application using our{' '} + + NPM library + +
+ npm install badge-maker + + ), + }, + { + title: 'Host your own instance', + description: ( + <> + Host a shields instance behind your firewall with our{' '} + + docker image + +
+ docker pull shieldsio/shields + + ), + }, + { + title: 'Love Shields?', + description: ( + <> + Please consider{' '} + + donating + {' '} + to sustain our activities + + ), + }, +] + +function Feature({ title, description }) { + return ( +
+
+

{title}

+

{description}

+
+
+ ) +} + +export default function HomepageFeatures() { + return ( +
+
+
+ {FeatureList.map((props, idx) => ( + + ))} +
+
+
+ ) +} diff --git a/src/components/homepage-features.module.css b/src/components/homepage-features.module.css new file mode 100644 index 0000000..aa5859e --- /dev/null +++ b/src/components/homepage-features.module.css @@ -0,0 +1,11 @@ +.features { + display: flex; + align-items: center; + padding: 2rem 0; + width: 100%; +} + +.featureSvg { + height: 200px; + width: 200px; +} diff --git a/src/css/custom.css b/src/css/custom.css new file mode 100644 index 0000000..cf4f03c --- /dev/null +++ b/src/css/custom.css @@ -0,0 +1,52 @@ +/** + * Any CSS included here will be global. The classic template + * bundles Infima by default. Infima is a CSS framework designed to + * work well for content-centric websites. + */ + +/* You can override the default Infima variables here. */ +:root { + --ifm-color-primary: #25c2a0; + --ifm-color-primary-dark: rgb(33, 175, 144); + --ifm-color-primary-darker: rgb(31, 165, 136); + --ifm-color-primary-darkest: rgb(26, 136, 112); + --ifm-color-primary-light: rgb(70, 203, 174); + --ifm-color-primary-lighter: rgb(102, 212, 189); + --ifm-color-primary-lightest: rgb(146, 224, 208); + --ifm-code-font-size: 95%; +} + +.docusaurus-highlight-code-line { + background-color: rgba(0, 0, 0, 0.1); + display: block; + margin: 0 calc(-1 * var(--ifm-pre-padding)); + padding: 0 var(--ifm-pre-padding); +} + +html[data-theme="dark"] .docusaurus-highlight-code-line { + background-color: rgba(0, 0, 0, 0.3); +} + +.opencollective-image { + color-scheme: initial; +} + +/* +TODO: remove these three styles when +we can upgrade to docusaurus-theme-openapi@0.6.5 +*/ + +input[type="text"], :not(#fakeID#fakeId#fakeID) select { + border-color: var(--ifm-color-primary-lightest); + border-style: solid; + border-width: 1px; +} + +div.api-code-tab-group { + justify-content: center; + flex-wrap: wrap; +} + +div.api-code-tab-group button.api-code-tab { + width: unset; +} diff --git a/src/pages/community.md b/src/pages/community.md new file mode 100644 index 0000000..54db53d --- /dev/null +++ b/src/pages/community.md @@ -0,0 +1,67 @@ +# Community + +Shields.io is possible thanks to the people and companies who donate money, services or time to keep the project running. + +## Sponsors + +❤️ These companies help us by donating their services to shields: + + + +💵 These organisations help keep shields running by donating on OpenCollective. Your organisation can support this project by becoming a sponsor . Your logo will show up here with a link to your website. + +

+ +

+ +## Backers + +💵 Thank you to all our backers who help keep shields running by donating on OpenCollective. You can support this project by becoming a backer. + +

+ + +

+ +## Contributors + +🙏 This project exists thanks to all the nice people who contribute their time to work on the project. + +

+ +

+ +✨ Shields is helped by these companies which provide a free plan for their product or service: + + diff --git a/src/pages/index.js b/src/pages/index.js new file mode 100644 index 0000000..e20aca5 --- /dev/null +++ b/src/pages/index.js @@ -0,0 +1,39 @@ +import React from 'react' +import clsx from 'clsx' +import Layout from '@theme/Layout' +import Link from '@docusaurus/Link' +import useDocusaurusContext from '@docusaurus/useDocusaurusContext' +import HomepageFeatures from '../components/homepage-features' +import styles from './index.module.css' + +function HomepageHeader() { + const { siteConfig } = useDocusaurusContext() + return ( +
+
+

{siteConfig.title}

+

{siteConfig.tagline}

+
+ + Get started + +
+
+
+ ) +} + +export default function Home() { + const { siteConfig } = useDocusaurusContext() + return ( + + +
+ +
+
+ ) +} diff --git a/src/pages/index.module.css b/src/pages/index.module.css new file mode 100644 index 0000000..dc85b3f --- /dev/null +++ b/src/pages/index.module.css @@ -0,0 +1,23 @@ +/** + * CSS files with the .module.css suffix will be treated as CSS modules + * and scoped locally. + */ + +.heroBanner { + padding: 4rem 0; + text-align: center; + position: relative; + overflow: hidden; +} + +@media screen and (max-width: 966px) { + .heroBanner { + padding: 2rem; + } +} + +.buttons { + display: flex; + align-items: center; + justify-content: center; +} diff --git a/src/plugins/strip-code-block-links.js b/src/plugins/strip-code-block-links.js new file mode 100644 index 0000000..278ac54 --- /dev/null +++ b/src/plugins/strip-code-block-links.js @@ -0,0 +1,30 @@ +const { visit } = require('unist-util-visit') + +function stripCodeBlockLinks() { + /* + Docusaurus 3 uses [remark-gfm](https://github.com/remarkjs/remark-gfm) + One of the "features" of remark-gfm is that it automatically looks for URLs + and email addresses, and automatically wraps them in tags. + + This happens even if the URL is inside a block. + This behaviour is + a) mostly unhelpful and + b) non-configurable + + This plugin removes tags which appear inside a block. + */ + return tree => { + visit(tree, ['mdxJsxTextElement', 'mdxJsxFlowElement', 'element'], node => { + if (node.name === 'code' || node.tagName === 'code') { + const links = node.children.filter(child => child.tagName === 'a') + links.forEach(link => { + const linkText = link.children.map(child => child.value).join('') + const linkIndex = node.children.indexOf(link) + node.children.splice(linkIndex, 1, { type: 'text', value: linkText }) + }) + } + }) + } +} + +module.exports = stripCodeBlockLinks diff --git a/src/theme/ApiDemoPanel/Curl/index.js b/src/theme/ApiDemoPanel/Curl/index.js new file mode 100644 index 0000000..ee6afd2 --- /dev/null +++ b/src/theme/ApiDemoPanel/Curl/index.js @@ -0,0 +1,300 @@ +import React, { useRef, useState, useEffect } from 'react' +import useDocusaurusContext from '@docusaurus/useDocusaurusContext' +import clsx from 'clsx' +import codegen from 'postman-code-generators' +import { Highlight } from 'prism-react-renderer' +import { useTypedSelector } from '@theme/ApiDemoPanel/hooks' +import buildPostmanRequest from '@theme/ApiDemoPanel/buildPostmanRequest' +import FloatingButton from '@theme/ApiDemoPanel/FloatingButton' +import styles from 'docusaurus-theme-openapi/lib/theme/ApiDemoPanel/Curl/styles.module.css' + +const languageSet = [ + { + tabName: 'cURL', + highlight: 'bash', + language: 'curl', + variant: 'curl', + options: { + longFormat: false, + followRedirect: true, + trimRequestBody: true, + }, + }, + { + tabName: 'Node', + highlight: 'javascript', + language: 'nodejs', + variant: 'axios', + options: { + ES6_enabled: true, + followRedirect: true, + trimRequestBody: true, + }, + }, + { + tabName: 'Go', + highlight: 'go', + language: 'go', + variant: 'native', + options: { + followRedirect: true, + trimRequestBody: true, + }, + }, + { + tabName: 'Python', + highlight: 'python', + language: 'python', + variant: 'requests', + options: { + followRedirect: true, + trimRequestBody: true, + }, + }, +] +const languageTheme = { + plain: { + color: 'var(--ifm-code-color)', + }, + styles: [ + { + types: ['inserted', 'attr-name'], + style: { + color: 'var(--openapi-code-green)', + }, + }, + { + types: ['string', 'url'], + style: { + color: 'var(--openapi-code-green)', + }, + }, + { + types: ['builtin', 'char', 'constant', 'function'], + style: { + color: 'var(--openapi-code-blue)', + }, + }, + { + types: ['punctuation', 'operator'], + style: { + color: 'var(--openapi-code-dim)', + }, + }, + { + types: ['class-name'], + style: { + color: 'var(--openapi-code-orange)', + }, + }, + { + types: ['tag', 'arrow', 'keyword'], + style: { + color: 'var(--openapi-code-purple)', + }, + }, + { + types: ['boolean'], + style: { + color: 'var(--openapi-code-red)', + }, + }, + ], +} + +function getBaseUrl() { + /* + This is a special case for production. + + We want to be able to build the front end with no value set for + `BASE_URL` so that staging, prod and self hosting users + can all use the same docker image. + + When deployed to staging, we want the frontend on + https://staging.shields.io/ to generate badges with the base + https://staging.shields.io/ + (and we want similar behaviour for users hosting their own instance) + + When we promote to production we want https://shields.io/ and + https://www.shields.io/ to both generate badges with the base + https://img.shields.io/ + + For local dev, we can deal with setting the api and front-end + being on different ports using the BASE_URL env var + */ + const { protocol, hostname, port } = window.location + if (['shields.io', 'www.shields.io'].includes(hostname)) { + return 'https://img.shields.io' + } + if (!port) { + return `${protocol}//${hostname}` + } + return `${protocol}//${hostname}:${port}` +} + +function getServer() { + return { + url: getBaseUrl(), + variables: {}, + } +} + +function Curl({ postman, codeSamples }) { + // TODO: match theme for vscode. + const { siteConfig } = useDocusaurusContext() + const [copyText, setCopyText] = useState('Copy') + const contentType = useTypedSelector(state => state.contentType.value) + const accept = useTypedSelector(state => state.accept.value) + const server = useTypedSelector(state => state.server.value) || getServer() + const body = useTypedSelector(state => state.body) + const pathParams = useTypedSelector(state => state.params.path) + const queryParams = useTypedSelector(state => state.params.query) + const cookieParams = useTypedSelector(state => state.params.cookie) + const headerParams = useTypedSelector(state => state.params.header) + const auth = useTypedSelector(state => state.auth) + + const langs = [ + ...(siteConfig?.themeConfig?.languageTabs ?? languageSet), + ...codeSamples, + ] + const [language, setLanguage] = useState(langs[0]) + const [codeText, setCodeText] = useState('') + useEffect(() => { + const postmanRequest = buildPostmanRequest(postman, { + queryParams, + pathParams, + cookieParams, + contentType, + accept, + headerParams, + body, + server, + auth, + }) + if (language && !!language.options) { + codegen.convert( + language.language, + language.variant, + postmanRequest, + language.options, + (error, snippet) => { + if (error) { + return + } + + setCodeText(snippet) + }, + ) + } else if (language && !!language.source) { + setCodeText( + language.source.replace('$url', postmanRequest.url.toString()), + ) + } else { + setCodeText('') + } + }, [ + accept, + body, + contentType, + cookieParams, + headerParams, + language, + pathParams, + postman, + queryParams, + server, + auth, + ]) + const ref = useRef(null) + + const handleCurlCopy = () => { + setCopyText('Copied') + setTimeout(() => { + setCopyText('Copy') + }, 2000) + + if (ref.current?.innerText) { + navigator.clipboard.writeText(ref.current.innerText) + } + } + + if (language === undefined) { + return null + } + + return ( + <> +
+ {langs.map(lang => ( + + ))} +
+ + + {({ className, tokens, getLineProps, getTokenProps }) => ( + +
+              
+                {tokens.map((line, i) => (
+                  // this  does have a key but eslint fails
+                  // to detect it because it is an arg to getLineProps()
+                  // eslint-disable-next-line react/jsx-key
+                  
+                    {line.map((token, key) => {
+                      if (token.types.includes('arrow')) {
+                        token.types = ['arrow']
+                      }
+
+                      return (
+                        // this  does have a key but eslint fails
+                        // to detect it because it is an arg to getLineProps()
+                        // eslint-disable-next-line react/jsx-key
+                        
+                      )
+                    })}
+                    {'\n'}
+                  
+                ))}
+              
+            
+
+ )} +
+ + ) +} + +export default Curl diff --git a/src/theme/ApiDemoPanel/Response/index.js b/src/theme/ApiDemoPanel/Response/index.js new file mode 100644 index 0000000..898e657 --- /dev/null +++ b/src/theme/ApiDemoPanel/Response/index.js @@ -0,0 +1,66 @@ +import React from 'react' +import { useTypedDispatch, useTypedSelector } from '@theme/ApiDemoPanel/hooks' +import FloatingButton from '@theme/ApiDemoPanel/FloatingButton' +import { clearResponse } from 'docusaurus-theme-openapi/lib/theme/ApiDemoPanel/Response/slice' + +function formatXml(xml) { + const tab = ' ' + let formatted = '' + let indent = '' + xml.split(/>\s* { + if (node.match(/^\/\w/)) { + // decrease indent by one 'tab' + indent = indent.substring(tab.length) + } + + formatted += `${indent}<${node}>\r\n` + + if (node.match(/^]*[^/]$/)) { + // increase indent + indent += tab + } + }) + return formatted.substring(1, formatted.length - 3) +} + +function Response() { + const response = useTypedSelector(state => state.response.value) + const dispatch = useTypedDispatch() + + if (response === undefined) { + return null + } + + let prettyResponse = response + + try { + prettyResponse = JSON.stringify(JSON.parse(response), null, 2) + } catch { + if (response.startsWith(' dispatch(clearResponse())}> + {(response.startsWith(' + )) || ( +
+          {prettyResponse || 'No Response'}
+        
+ )} + + ) +} + +export default Response diff --git a/src/theme/DocPaginator/index.js b/src/theme/DocPaginator/index.js new file mode 100644 index 0000000..7096842 --- /dev/null +++ b/src/theme/DocPaginator/index.js @@ -0,0 +1,3 @@ +export default function DocPaginator(props) { + return '' +} diff --git a/static/.nojekyll b/static/.nojekyll new file mode 100644 index 0000000..473a0f4 diff --git a/static/img/builder.png b/static/img/builder.png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..4316ba2677a4d91cd748819b01227cd68e5e556311cb8cdc5c78c293df633c29 GIT binary patch literal 31273 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 KzLbj^{QO_s9SOq# literal 0 HcmV?d00001 diff --git a/static/img/favicon.ico b/static/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..cf73624bea1a816a6cafcc3f9ebf155985336b3324ddf00712c8bd939d48f9cc GIT binary patch literal 15086 zcmeHOziSjx5S}%PjdDS(QXQyZC1)d8DFjPJxV-}ngexorEmS0hRVqOb)9CHxPl%<3 zA*4zW%w7Hf!9uyt)<586oo{z1KF{6T+aJ$!aTX?%-R#@>-t0H?=DmF(a%h1X4PsrV ztqVj~h^StV&KHTk^0h_Q`1}3iM9=w#i+m3^p$-eK2gmtP{VzW+cb_b|u6v`1I0wDu zA_5Fq{4JPUt=2Y+Uqo)N-0{!6d*RbzKfesU&(6Sm%RX35>j$uxfm`}q3Vx&S=tt7~ zC>uNaP&R(N$D}^6y*2S$S=t8vpbrPV2PT(n_}-TPgIMC2FnNUhQkKun=h*Up^bVHg z9k9*PxntG;hyx=ZRS`c8y@yryzv53Hn{CFg`d|GYj73I$lj&UZPik$g@jGSSp!`w( z&HJ;Z0spFc> z{9~@4SN;1%)xRHM62N(;^lvb>_`}@!?fV_@+js{y@F#sgwb6&N@lV4J{BlI`T)F)N zf?qT^Rb=l5+A>%F>i!MEUKQ;J2a)J8fL|l}4qYP}L7)7k_i(;Iq&nUYBff0-b(W)jTD+HQmg7?Q@hKaUX1m#Jp5yUq(`~o*XO&|EZ+}*ChF*{3_G%ms zwtJ7|3rlMKB=_7}z3bQBceCw*8uq_AgI>qP5cNBgZD7b{KUgDY42B>0S)0;*ofZG|&a1e2{FwKX?TFpDws^*r_ITzPIQYH|u{Wtx+Vh^a z{!4AI{+r~DoX^4^#0=m62lw%el=cCCi^h+{VO;FuT3Y=2KGC`p%4BXxI+y#=_9xKo BaLNDx literal 0 HcmV?d00001 diff --git a/static/img/logo.png b/static/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..0e33bbdc89aa2c26925c13e9298048721d585de166ae413301622f01bc3cbbd7 GIT binary patch literal 16615 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 literal 0 HcmV?d00001