add support for custom stylesheets

This commit is contained in:
mat 2024-06-29 02:01:05 -05:00
parent 24b8bb749c
commit 09435e4d86
8 changed files with 92 additions and 20 deletions

6
README
View File

@ -17,3 +17,9 @@ run of metasearch2. alternatively, you can copy the config-default.toml in the
repo and rename it to config.toml. repo and rename it to config.toml.
the default port is 28019. the default port is 28019.
API
metasearch has a JSON API that can be enabled by setting `api = true` in your config. to use it,
just set the `Accept: application/json` header. as the api works by serializing internal structs,
it's not guaranteed to be stable across metasearch versions.

View File

@ -6,6 +6,7 @@ api = false
[ui] [ui]
# engine_list_separator = true # engine_list_separator = true
# version_info = true # version_info = true
# stylesheet_url = "/themes/catppuccin-mocha.css"
[engines] [engines]
# numbat = false # numbat = false

View File

@ -39,6 +39,8 @@ impl Config {
pub struct UiConfig { pub struct UiConfig {
pub show_engine_list_separator: bool, pub show_engine_list_separator: bool,
pub show_version_info: bool, pub show_version_info: bool,
pub stylesheet_url: Option<String>,
pub stylesheet_str: Option<String>,
} }
#[derive(Deserialize, Debug, Default)] #[derive(Deserialize, Debug, Default)]
@ -47,6 +49,10 @@ pub struct PartialUiConfig {
pub show_engine_list_separator: Option<bool>, pub show_engine_list_separator: Option<bool>,
#[serde(default)] #[serde(default)]
pub show_version_info: Option<bool>, pub show_version_info: Option<bool>,
#[serde(default)]
pub stylesheet_url: Option<String>,
#[serde(default)]
pub stylesheet_str: Option<String>,
} }
impl UiConfig { impl UiConfig {
@ -55,6 +61,7 @@ impl UiConfig {
.show_engine_list_separator .show_engine_list_separator
.unwrap_or(self.show_engine_list_separator); .unwrap_or(self.show_engine_list_separator);
self.show_version_info = partial.show_version_info.unwrap_or(self.show_version_info); self.show_version_info = partial.show_version_info.unwrap_or(self.show_version_info);
self.stylesheet_url = partial.stylesheet_url.or(self.stylesheet_url.clone());
} }
} }
@ -202,6 +209,8 @@ impl Default for Config {
ui: UiConfig { ui: UiConfig {
show_engine_list_separator: false, show_engine_list_separator: false,
show_version_info: false, show_version_info: false,
stylesheet_url: None,
stylesheet_str: None,
}, },
image_search: ImageSearchConfig { image_search: ImageSearchConfig {
enabled: false, enabled: false,

2
src/web/assets/README Normal file
View File

@ -0,0 +1,2 @@
files added in this directory aren't automatically made accessible, you have to add them as a route
in src/web/mod.rs (so the files are included in the binary)

View File

@ -0,0 +1,29 @@
:root {
/* body background */
--bg-1: #11111b;
/* background of the content */
--bg-2: #181825;
/* input suggestions background */
--bg-3: #1e1e2e;
/* mostly borders */
--bg-4: #313244;
/* main text color */
--fg-1: #cdd6f4;
/* search result description */
--fg-2: #bac2de;
--fg-3: #a6adc8;
/* focus outline */
--accent: #b4befe;
--link: #89b4fa;
--link-visited: #bc78f8;
--positive: #7fd962;
--syntax-string: #aad94c;
--syntax-special: #e6b673;
--syntax-constant: #d2a6ff;
--syntax-comment: #acb6bf8c;
}

View File

@ -22,6 +22,12 @@ pub async fn index(State(config): State<Arc<Config>>) -> impl IntoResponse {
meta name="viewport" content="width=device-width, initial-scale=1.0"; meta name="viewport" content="width=device-width, initial-scale=1.0";
title { "metasearch" } title { "metasearch" }
link rel="stylesheet" href="/style.css"; link rel="stylesheet" href="/style.css";
@if let Some(stylesheet_url) = &config.ui.stylesheet_url {
link rel="stylesheet" href=(stylesheet_url);
}
@if let Some(stylesheet_str) = &config.ui.stylesheet_str {
link rel="stylesheet" href=(stylesheet_str);
}
script src="/script.js" defer {} script src="/script.js" defer {}
link rel="search" type="application/opensearchdescription+xml" title="metasearch" href="/opensearch.xml"; link rel="search" type="application/opensearchdescription+xml" title="metasearch" href="/opensearch.xml";
} }

View File

@ -4,9 +4,13 @@ pub mod index;
pub mod opensearch; pub mod opensearch;
pub mod search; pub mod search;
use std::{net::SocketAddr, sync::Arc}; use std::{convert::Infallible, net::SocketAddr, sync::Arc};
use axum::{http::header, routing::get, Router}; use axum::{
http::header,
routing::{get, MethodRouter},
Router,
};
use tracing::info; use tracing::info;
use crate::config::Config; use crate::config::Config;
@ -14,34 +18,43 @@ use crate::config::Config;
pub async fn run(config: Config) { pub async fn run(config: Config) {
let bind_addr = config.bind; let bind_addr = config.bind;
fn static_route<S>(
content: &'static str,
content_type: &'static str,
) -> MethodRouter<S, Infallible>
where
S: Clone + Send + Sync + 'static,
{
let response = ([(header::CONTENT_TYPE, content_type)], content);
get(|| async { response })
}
let app = Router::new() let app = Router::new()
.route("/", get(index::index)) .route("/", get(index::index))
.route( .route(
"/style.css", "/style.css",
get(|| async { static_route(include_str!("assets/style.css"), "text/css; charset=utf-8"),
(
[(header::CONTENT_TYPE, "text/css; charset=utf-8")],
include_str!("assets/style.css"),
)
}),
) )
.route( .route(
"/script.js", "/script.js",
get(|| async { static_route(
( include_str!("assets/script.js"),
[(header::CONTENT_TYPE, "text/javascript; charset=utf-8")], "text/javascript; charset=utf-8",
include_str!("assets/script.js"), ),
)
}),
) )
.route( .route(
"/robots.txt", "/robots.txt",
get(|| async { static_route(
( include_str!("assets/robots.txt"),
[(header::CONTENT_TYPE, "text/plain; charset=utf-8")], "text/plain; charset=utf-8",
include_str!("assets/robots.txt"), ),
) )
}), .route(
"/themes/catppuccin-mocha.css",
static_route(
include_str!("assets/themes/catppuccin-mocha.css"),
"text/css; charset=utf-8",
),
) )
.route("/opensearch.xml", get(opensearch::route)) .route("/opensearch.xml", get(opensearch::route))
.route("/search", get(search::route)) .route("/search", get(search::route))

View File

@ -32,6 +32,12 @@ fn render_beginning_of_html(search: &SearchQuery) -> String {
" - metasearch" " - metasearch"
} }
link rel="stylesheet" href="/style.css"; link rel="stylesheet" href="/style.css";
@if let Some(stylesheet_url) = &search.config.ui.stylesheet_url {
link rel="stylesheet" href=(stylesheet_url);
}
@if let Some(stylesheet_str) = &search.config.ui.stylesheet_str {
link rel="stylesheet" href=(stylesheet_str);
}
script src="/script.js" defer {} script src="/script.js" defer {}
link rel="search" type="application/opensearchdescription+xml" title="metasearch" href="/opensearch.xml"; link rel="search" type="application/opensearchdescription+xml" title="metasearch" href="/opensearch.xml";
} }