predawn/plugin/ui/
rapidoc.rs

1use std::sync::Arc;
2
3use http::Method;
4use indexmap::IndexMap;
5use rudi::{Context, Singleton};
6
7use crate::{config::Config, handler::DynHandler, normalized_path::NormalizedPath, plugin::Plugin};
8
9const TEMPLATE: &str = r###"
10<!DOCTYPE html>
11<html>
12  <head>
13    <meta charset="utf-8" />
14    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
15    <meta name="description" content="{{description}}" />
16    <title>{{title}}</title>
17    <script type="module" src="{{js_url}}"></script>
18  </head>
19  <body>
20    <rapi-doc spec-url="{{spec_url}}"> </rapi-doc>
21  </body>
22</html>
23"###;
24
25#[derive(Clone, Debug)]
26pub struct RapiDoc {
27    description: Box<str>,
28    title: Box<str>,
29    js_url: Box<str>,
30    spec_url: Box<str>,
31}
32
33impl Plugin for RapiDoc {
34    fn create_route(
35        self: Arc<Self>,
36        cx: &mut Context,
37    ) -> (NormalizedPath, IndexMap<Method, DynHandler>) {
38        super::create_route(cx, |c| c.rapidoc_path, self.as_html())
39    }
40}
41
42fn condition(cx: &Context) -> bool {
43    !cx.contains_provider::<RapiDoc>()
44}
45
46#[Singleton(condition = condition)]
47fn RapiDocRegister(#[di(ref)] cfg: &Config) -> RapiDoc {
48    let json_path = super::json_path(cfg).into_inner();
49    RapiDoc::new(json_path)
50}
51
52#[Singleton(name = std::any::type_name::<RapiDoc>())]
53fn RapiDocToPlugin(rapidoc: RapiDoc) -> Arc<dyn Plugin> {
54    Arc::new(rapidoc)
55}
56
57impl RapiDoc {
58    pub fn new<T>(spec_url: T) -> Self
59    where
60        T: Into<Box<str>>,
61    {
62        Self {
63            description: Box::from("RapiDoc"),
64            title: Box::from("RapiDoc"),
65            js_url: Box::from("https://unpkg.com/rapidoc/dist/rapidoc-min.js"),
66            spec_url: spec_url.into(),
67        }
68    }
69
70    pub fn as_html(&self) -> String {
71        TEMPLATE
72            .replacen("{{description}}", &self.description, 1)
73            .replacen("{{title}}", &self.title, 1)
74            .replacen("{{js_url}}", &self.js_url, 1)
75            .replacen("{{spec_url}}", &self.spec_url, 1)
76    }
77}