From a7528c74a5f00a7f29787c7e9d09dc448d9a01e0 Mon Sep 17 00:00:00 2001 From: xitep Date: Wed, 6 Nov 2024 13:16:26 +0100 Subject: [PATCH] Allow disabling syntax highlighting (#1188) Add support for disabling highlights from Swagger UI responses and cURL commands as well as changing the theme of the highlight. --- utoipa-swagger-ui/CHANGELOG.md | 6 + utoipa-swagger-ui/src/lib.rs | 201 +++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) diff --git a/utoipa-swagger-ui/CHANGELOG.md b/utoipa-swagger-ui/CHANGELOG.md index 39641484..cbd839f5 100644 --- a/utoipa-swagger-ui/CHANGELOG.md +++ b/utoipa-swagger-ui/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog - utoipa-swagger-ui +## Unreleased + +### Added + +* Allow disabling syntax highlighting (https://github.com/juhaku/utoipa/pull/1188) + ## 8.0.3 - Oct 23 2024 ### Fixed diff --git a/utoipa-swagger-ui/src/lib.rs b/utoipa-swagger-ui/src/lib.rs index 4e98f347..ab8823aa 100644 --- a/utoipa-swagger-ui/src/lib.rs +++ b/utoipa-swagger-ui/src/lib.rs @@ -663,6 +663,10 @@ pub struct Config<'a> { #[serde(skip)] oauth: Option, + /// Defines syntax highlighting specific options. + #[serde(skip_serializing_if = "Option::is_none")] + syntax_highlight: Option, + /// The layout of Swagger UI uses, default is `"StandaloneLayout"`. layout: &'a str, } @@ -1243,6 +1247,27 @@ impl<'a> Config<'a> { self } + + /// Set a specific configuration for syntax highlighting responses + /// and curl commands. + /// + /// By default, swagger-ui does syntax highlighting of responses + /// and curl commands. This may consume considerable resources in + /// the browser when executed on large responses. + /// + /// # Example + /// + /// Disable syntax highlighting. + /// ```rust + /// # use utoipa_swagger_ui::Config; + /// let config = Config::new(["/api-docs/openapi.json"]) + /// .with_syntax_highlight(false); + /// ``` + pub fn with_syntax_highlight>(mut self, syntax_highlight: H) -> Self { + self.syntax_highlight = Some(syntax_highlight.into()); + + self + } } impl Default for Config<'_> { @@ -1274,6 +1299,7 @@ impl Default for Config<'_> { with_credentials: Default::default(), persist_authorization: Default::default(), oauth: Default::default(), + syntax_highlight: Default::default(), layout: SWAGGER_STANDALONE_LAYOUT, } } @@ -1291,6 +1317,54 @@ impl From for Config<'_> { } } +/// Represents settings related to syntax highlighting of payloads and +/// cURL commands. +#[derive(Serialize, Clone)] +#[non_exhaustive] +pub struct SyntaxHighlight { + /// Boolean telling whether syntax highlighting should be + /// activated or not. Defaults to `true`. + pub activated: bool, + /// Highlight.js syntax coloring theme to use. + #[serde(skip_serializing_if = "Option::is_none")] + pub theme: Option<&'static str>, +} + +impl Default for SyntaxHighlight { + fn default() -> Self { + Self { + activated: true, + theme: None, + } + } +} + +impl From for SyntaxHighlight { + fn from(value: bool) -> Self { + Self { + activated: value, + ..Default::default() + } + } +} + +impl SyntaxHighlight { + /// Explicitly specifies whether syntax highlighting is to be + /// activated or not. Defaults to true. + pub fn activated(mut self, activated: bool) -> Self { + self.activated = activated; + self + } + + /// Explicitly specifies the + /// [Highlight.js](https://highlightjs.org/) coloring theme to + /// utilize for syntax highlighting. + pub fn theme(mut self, theme: &'static str) -> Self { + self.theme = Some(theme); + self + } +} + /// Represents servable file of Swagger UI. This is used together with [`serve`] function /// to serve Swagger UI files via web server. #[non_exhaustive] @@ -1691,4 +1765,131 @@ window.ui = SwaggerUIBundle({ assert_diff_equal(EXPECTED, &formatted_config); } + + #[test] + fn format_swagger_config_with_syntax_highlight_default() { + let formatted_config = match format_config( + &Config::new(["/api-docs/openapi1.json"]) + .with_syntax_highlight(SyntaxHighlight::default()), + String::from(TEST_INITIAL_CONFIG), + ) { + Ok(file) => file, + Err(error) => panic!("{error}"), + }; + + const EXPECTED: &str = r###" +window.ui = SwaggerUIBundle({ + "dom_id": "#swagger-ui", + "url": "/api-docs/openapi1.json", + "deepLinking": true, + "syntaxHighlight": { + "activated": true + }, + "layout": "StandaloneLayout", + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + plugins: [ + SwaggerUIBundle.plugins.DownloadUrl + ], +});"###; + + assert_diff_equal(EXPECTED, &formatted_config); + } + + #[test] + fn format_swagger_config_with_syntax_highlight_on() { + let formatted_config = match format_config( + &Config::new(["/api-docs/openapi1.json"]).with_syntax_highlight(true), + String::from(TEST_INITIAL_CONFIG), + ) { + Ok(file) => file, + Err(error) => panic!("{error}"), + }; + + const EXPECTED: &str = r###" +window.ui = SwaggerUIBundle({ + "dom_id": "#swagger-ui", + "url": "/api-docs/openapi1.json", + "deepLinking": true, + "syntaxHighlight": { + "activated": true + }, + "layout": "StandaloneLayout", + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + plugins: [ + SwaggerUIBundle.plugins.DownloadUrl + ], +});"###; + + assert_diff_equal(EXPECTED, &formatted_config); + } + + #[test] + fn format_swagger_config_with_syntax_highlight_off() { + let formatted_config = match format_config( + &Config::new(["/api-docs/openapi1.json"]).with_syntax_highlight(false), + String::from(TEST_INITIAL_CONFIG), + ) { + Ok(file) => file, + Err(error) => panic!("{error}"), + }; + + const EXPECTED: &str = r###" +window.ui = SwaggerUIBundle({ + "dom_id": "#swagger-ui", + "url": "/api-docs/openapi1.json", + "deepLinking": true, + "syntaxHighlight": { + "activated": false + }, + "layout": "StandaloneLayout", + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + plugins: [ + SwaggerUIBundle.plugins.DownloadUrl + ], +});"###; + + assert_diff_equal(EXPECTED, &formatted_config); + } + + #[test] + fn format_swagger_config_with_syntax_highlight_default_with_theme() { + let formatted_config = match format_config( + &Config::new(["/api-docs/openapi1.json"]) + .with_syntax_highlight(SyntaxHighlight::default().theme("monokai")), + String::from(TEST_INITIAL_CONFIG), + ) { + Ok(file) => file, + Err(error) => panic!("{error}"), + }; + + const EXPECTED: &str = r###" +window.ui = SwaggerUIBundle({ + "dom_id": "#swagger-ui", + "url": "/api-docs/openapi1.json", + "deepLinking": true, + "syntaxHighlight": { + "activated": true, + "theme": "monokai" + }, + "layout": "StandaloneLayout", + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + plugins: [ + SwaggerUIBundle.plugins.DownloadUrl + ], +});"###; + + assert_diff_equal(EXPECTED, &formatted_config); + } }