Add support for Stoplight Elements (#954)

* Add support for Stoplight Elements

* Improve the display of union types in the Stoplight element UI
This commit is contained in:
bxneter
2025-02-12 14:27:30 +07:00
committed by GitHub
parent 85741b2758
commit fd75eb3ca2
8 changed files with 99 additions and 41 deletions

View File

@@ -333,6 +333,7 @@ pub(crate) fn generate(args: DeriveInput) -> GeneratorResult<TokenStream> {
};
let meta = quote! {
#crate_name::registry::MetaSchema {
title: ::std::option::Option::Some(#object_name),
description: #description,
external_docs: #external_docs,
required: {

View File

@@ -17,6 +17,7 @@ categories = ["network-programming", "asynchronous"]
swagger-ui = []
rapidoc = []
redoc = []
stoplight-elements = []
openapi-explorer = []
email = ["email_address"]
hostname = ["hostname-validator"]

View File

@@ -50,26 +50,27 @@ important business implementations.
To avoid compiling unused dependencies, Poem gates certain features, some of which are disabled by default:
| Feature | Description |
|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| chrono | Integrate with the [`chrono` crate](https://crates.io/crates/chrono). |
| time | Integrate with the [`time` crate](https://crates.io/crates/time). |
| humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
| openapi-explorer | Add OpenAPI Explorer support |
| swagger-ui | Add swagger UI support |
| rapidoc | Add RapiDoc UI support |
| redoc | Add Redoc UI support |
| email | Support for email address string |
| hostname | Support for hostname string |
| uuid | Integrate with the [`uuid` crate](https://crates.io/crates/uuid) |
| url | Integrate with the [`url` crate](https://crates.io/crates/url) |
| geo | Integrate with the [`geo-types` crate](https://crates.io/crates/geo-types) |
| bson | Integrate with the [`bson` crate](https://crates.io/crates/bson) |
| rust_decimal | Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal) |
| prost-wkt-types | Integrate with the [`prost-wkt-types` crate](https://crates.io/crates/prost-wkt-types) |
| static-files | Support for static file response |
| websocket | Support for websocket |
| sonic-rs | Uses [`sonic-rs`](https://github.com/cloudwego/sonic-rs) instead of `serde_json`. Pls, checkout `sonic-rs` requirements to properly enable `sonic-rs` capabilities |
| Feature | Description |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| chrono | Integrate with the [`chrono` crate](https://crates.io/crates/chrono). |
| time | Integrate with the [`time` crate](https://crates.io/crates/time). |
| humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
| openapi-explorer | Add OpenAPI Explorer support |
| swagger-ui | Add swagger UI support |
| rapidoc | Add RapiDoc UI support |
| redoc | Add Redoc UI support |
| stoplight-elements | Add Stoplight Elements UI support |
| email | Support for email address string |
| hostname | Support for hostname string |
| uuid | Integrate with the [`uuid` crate](https://crates.io/crates/uuid) |
| url | Integrate with the [`url` crate](https://crates.io/crates/url) |
| geo | Integrate with the [`geo-types` crate](https://crates.io/crates/geo-types) |
| bson | Integrate with the [`bson` crate](https://crates.io/crates/bson) |
| rust_decimal | Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal) |
| prost-wkt-types | Integrate with the [`prost-wkt-types` crate](https://crates.io/crates/prost-wkt-types) |
| static-files | Support for static file response |
| websocket | Support for websocket |
| sonic-rs | Uses [`sonic-rs`](https://github.com/cloudwego/sonic-rs) instead of `serde_json`. Pls, checkout `sonic-rs` requirements to properly enable `sonic-rs` capabilities |
## Safety

View File

@@ -92,27 +92,28 @@
//! To avoid compiling unused dependencies, Poem gates certain features, some of
//! which are disabled by default:
//!
//! | Feature | Description |
//! |------------------|----------------------------------------------------------------------------------------|
//! | chrono | Integrate with the [`chrono` crate](https://crates.io/crates/chrono). |
//! | time | Integrate with the [`time` crate](https://crates.io/crates/time). |
//! | humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
//! | openapi-explorer | Add OpenAPI Explorer support |
//! | swagger-ui | Add swagger UI support |
//! | rapidoc | Add RapiDoc UI support |
//! | redoc | Add Redoc UI support |
//! | email | Support for email address string |
//! | hostname | Support for hostname string |
//! | humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
//! | uuid | Integrate with the [`uuid` crate](https://crates.io/crates/uuid) |
//! | url | Integrate with the [`url` crate](https://crates.io/crates/url) |
//! | geo | Integrate with the [`geo-types` crate](https://crates.io/crates/geo-types) |
//! | bson | Integrate with the [`bson` crate](https://crates.io/crates/bson) |
//! | rust_decimal | Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal) |
//! | prost-wkt-types | Integrate with the [`prost-wkt-types` crate](https://crates.io/crates/prost-wkt-types) |
//! | static-files | Support for static file response |
//! | websocket | Support for websocket |
//! |sonic-rs | Uses [`sonic-rs`](https://github.com/cloudwego/sonic-rs) instead of `serde_json`. Pls, checkout `sonic-rs` requirements to properly enable `sonic-rs` capabilities |
//! | Feature | Description |
//! |--------------------|----------------------------------------------------------------------------------------|
//! | chrono | Integrate with the [`chrono` crate](https://crates.io/crates/chrono). |
//! | time | Integrate with the [`time` crate](https://crates.io/crates/time). |
//! | humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
//! | openapi-explorer | Add OpenAPI Explorer support |
//! | swagger-ui | Add swagger UI support |
//! | rapidoc | Add RapiDoc UI support |
//! | redoc | Add Redoc UI support |
//! | stoplight-elements | Add Stoplight Elements UI support |
//! | email | Support for email address string |
//! | hostname | Support for hostname string |
//! | humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
//! | uuid | Integrate with the [`uuid` crate](https://crates.io/crates/uuid) |
//! | url | Integrate with the [`url` crate](https://crates.io/crates/url) |
//! | geo | Integrate with the [`geo-types` crate](https://crates.io/crates/geo-types) |
//! | bson | Integrate with the [`bson` crate](https://crates.io/crates/bson) |
//! | rust_decimal | Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal) |
//! | prost-wkt-types | Integrate with the [`prost-wkt-types` crate](https://crates.io/crates/prost-wkt-types) |
//! | static-files | Support for static file response |
//! | websocket | Support for websocket |
//! | sonic-rs | Uses [`sonic-rs`](https://github.com/cloudwego/sonic-rs) instead of `serde_json`. Pls, checkout `sonic-rs` requirements to properly enable `sonic-rs` capabilities |
#![doc(html_favicon_url = "https://raw.githubusercontent.com/poem-web/poem/master/favicon.ico")]
#![doc(html_logo_url = "https://raw.githubusercontent.com/poem-web/poem/master/logo.png")]

View File

@@ -471,6 +471,28 @@ impl<T, W> OpenApiService<T, W> {
crate::ui::redoc::create_html(&self.spec())
}
/// Create the Stoplight Elements endpoint.
#[must_use]
#[cfg(feature = "stoplight-elements")]
pub fn stoplight_elements(&self) -> impl Endpoint
where
T: OpenApi,
W: Webhook,
{
crate::ui::stoplight_elements::create_endpoint(&self.spec())
}
/// Create the Stoplight Elements HTML.
#[must_use]
#[cfg(feature = "stoplight-elements")]
pub fn stoplight_elements_html(&self) -> String
where
T: OpenApi,
W: Webhook,
{
crate::ui::stoplight_elements::create_html(&self.spec())
}
/// Create an endpoint to serve the open api specification as JSON.
pub fn spec_endpoint(&self) -> impl Endpoint
where

View File

@@ -4,5 +4,7 @@ pub(crate) mod openapi_explorer;
pub(crate) mod rapidoc;
#[cfg(feature = "redoc")]
pub(crate) mod redoc;
#[cfg(feature = "stoplight-elements")]
pub(crate) mod stoplight_elements;
#[cfg(feature = "swagger-ui")]
pub(crate) mod swagger_ui;

View File

@@ -0,0 +1,12 @@
use poem::{endpoint::make_sync, web::Html, Endpoint};
const TEMPLATE: &str = include_str!("stoplight-elements.html");
pub(crate) fn create_html(document: &str) -> String {
TEMPLATE.replace("'{:spec}'", document)
}
pub(crate) fn create_endpoint(document: &str) -> impl Endpoint {
let ui_html = create_html(document);
poem::Route::new().at("/", make_sync(move |_| Html(ui_html.clone())))
}

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>OpenAPI</title>
<!-- Embed elements Elements via Web Component -->
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css" />
</head>
<body>
<elements-api id="docs" layout="responsive" router="hash" />
<script>
document.getElementById('docs').apiDescriptionDocument = '{:spec}';
</script>
</body>
</html>