aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md7
-rw-r--r--data/style.scss55
-rw-r--r--src/args.rs26
-rw-r--r--src/auth.rs2
-rw-r--r--src/file_upload.rs17
-rw-r--r--src/listing.rs6
-rw-r--r--src/main.rs18
-rw-r--r--src/renderer.rs14
8 files changed, 127 insertions, 18 deletions
diff --git a/README.md b/README.md
index 1be86ec..7bd7463 100644
--- a/README.md
+++ b/README.md
@@ -106,8 +106,11 @@ Sometimes this is just a more practical and quick way than doing things properly
username:sha512:hash (e.g. joe:123,
joe:sha256:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3)
-c, --color-scheme <color-scheme>
- Default color scheme [default: Squirrel] [possible values: Archlinux, Zenburn,
- Monokai, Squirrel]
+ Default color scheme [default: squirrel] [possible values: squirrel, archlinux, zenburn, monokai]
+
+ -d, --color-scheme-dark <color-scheme-dark>
+ Default color scheme [default: archlinux] [possible values: squirrel, archlinux, zenburn, monokai]
+
--index <index_file>
The name of a directory index file to serve, like "index.html"
diff --git a/data/style.scss b/data/style.scss
index 635dd9e..0871632 100644
--- a/data/style.scss
+++ b/data/style.scss
@@ -1,8 +1,17 @@
+@use "sass:selector";
+
/* theme colors can be found at the bottom */
$themes: squirrel, archlinux, monokai, zenburn;
-$default_theme: squirrel;
-$default_theme_dark: archlinux;
+@function body_not_themed() {
+ $s: unquote("body");
+ @each $t in $themes {
+ $s: selector.append($s, unquote(":not(.theme_#{$t})"));
+ }
+ @return $s;
+}
+
+
html {
font-smoothing: antialiased;
@@ -167,16 +176,19 @@ nav .theme li a:hover {
color: var(--change_theme_link_color_hover);
}
+%active_theme_link {
+ font-weight: bold;
+ color: var(--switch_theme_active);
+}
+
@each $theme in $themes {
body.theme_#{$theme} nav .theme li.theme_#{$theme} a {
- font-weight: bold;
- color: var(--switch_theme_active);
+ @extend %active_theme_link;
}
}
-body:not([class^="theme_"]) nav .theme li.theme_default a {
- font-weight: bold;
- color: var(--switch_theme_active);
+#{body_not_themed()} nav .theme li.theme_default a {
+ @extend %active_theme_link;
}
p {
@@ -681,12 +693,31 @@ th span.active span {
--error_color: #d02929;
}
-/* theme picked by user */
+
+@each $theme in $themes {
+ %theme_#{$theme} { @include theme_#{$theme}; }
+
+ body.theme_#{$theme} { @extend %theme_#{$theme}; }
+
+ #{body_not_themed()}.default_theme_#{$theme} {
+ @extend %theme_#{$theme};
+ }
+}
+
+// this needs to be in a separate loop below the first,
+// because dark mode doesn't add to specificity, so
+// the dark defaults need to come after the light defaults
+// to override them
@each $theme in $themes {
- body.theme_#{$theme} { @include theme_#{$theme}; }
+ @media (prefers-color-scheme: dark) {
+ %theme_dark_#{$theme} { @include theme_#{$theme}; }
+ }
+
+ // this extension will still end up inside the media query,
+ // because that is where %theme_dark_* was defined
+ #{body_not_themed()}.default_theme_dark_#{$theme} {
+ @extend %theme_dark_#{$theme};
+ }
}
-/* defaults */
-body { @include theme_#{$default_theme}; }
-@media (prefers-color-scheme: dark) { body { @include theme_#{$default_theme_dark}; } }
diff --git a/src/args.rs b/src/args.rs
index 78f9ce3..dc160d0 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -5,6 +5,7 @@ use structopt::StructOpt;
use crate::auth;
use crate::errors::ContextualError;
+use crate::renderer;
/// Possible characters for random routes
const ROUTE_ALPHABET: [char; 16] = [
@@ -66,6 +67,26 @@ struct CLIArgs {
#[structopt(short = "P", long = "no-symlinks")]
no_symlinks: bool,
+ /// Default color scheme
+ #[structopt(
+ short = "c",
+ long = "color-scheme",
+ default_value = "squirrel",
+ possible_values = &renderer::THEME_SLUGS,
+ case_insensitive = true,
+ )]
+ color_scheme: String,
+
+ /// Default color scheme
+ #[structopt(
+ short = "d",
+ long = "color-scheme-dark",
+ default_value = "archlinux",
+ possible_values = &renderer::THEME_SLUGS,
+ case_insensitive = true,
+ )]
+ color_scheme_dark: String,
+
/// Enable QR code display
#[structopt(short = "q", long = "qrcode")]
qrcode: bool,
@@ -169,6 +190,9 @@ pub fn parse_args() -> crate::MiniserveConfig {
let favicon_route = nanoid::nanoid!(10, &ROUTE_ALPHABET);
let css_route = nanoid::nanoid!(10, &ROUTE_ALPHABET);
+ let default_color_scheme = args.color_scheme;
+ let default_color_scheme_dark = args.color_scheme_dark;
+
let path_explicitly_chosen = args.path.is_some();
let port = match args.port {
@@ -187,6 +211,8 @@ pub fn parse_args() -> crate::MiniserveConfig {
random_route,
favicon_route,
css_route,
+ default_color_scheme,
+ default_color_scheme_dark,
index: args.index,
overwrite_files: args.overwrite_files,
show_qrcode: args.qrcode,
diff --git a/src/auth.rs b/src/auth.rs
index 3233e22..a2dfe60 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -124,6 +124,8 @@ fn build_unauthorized_response(
false,
&state.favicon_route,
&state.css_route,
+ &state.default_color_scheme,
+ &state.default_color_scheme_dark,
)
.into_string()
}
diff --git a/src/file_upload.rs b/src/file_upload.rs
index 3afa755..14aadfc 100644
--- a/src/file_upload.rs
+++ b/src/file_upload.rs
@@ -111,6 +111,8 @@ pub fn upload_file(
uses_random_route: bool,
favicon_route: String,
css_route: String,
+ default_color_scheme: &str,
+ default_color_scheme_dark: &str,
) -> Pin<Box<dyn Future<Output = Result<HttpResponse, actix_web::Error>>>> {
let conf = req.app_data::<crate::MiniserveConfig>().unwrap();
let return_path = if let Some(header) = req.headers().get(header::REFERER) {
@@ -138,6 +140,8 @@ pub fn upload_file(
uses_random_route,
&favicon_route,
&css_route,
+ default_color_scheme,
+ default_color_scheme_dark,
));
}
};
@@ -158,6 +162,8 @@ pub fn upload_file(
uses_random_route,
&favicon_route,
&css_route,
+ default_color_scheme,
+ default_color_scheme_dark,
));
}
};
@@ -178,10 +184,15 @@ pub fn upload_file(
uses_random_route,
&favicon_route,
&css_route,
+ default_color_scheme,
+ default_color_scheme_dark,
));
}
};
let overwrite_files = conf.overwrite_files;
+ let default_color_scheme = conf.default_color_scheme.clone();
+ let default_color_scheme_dark = conf.default_color_scheme_dark.clone();
+
Box::pin(
actix_multipart::Multipart::new(req.headers(), payload)
.map_err(ContextualError::MultipartError)
@@ -203,6 +214,8 @@ pub fn upload_file(
uses_random_route,
&favicon_route,
&css_route,
+ &default_color_scheme,
+ &default_color_scheme_dark,
),
}),
)
@@ -219,6 +232,8 @@ fn create_error_response(
uses_random_route: bool,
favicon_route: &str,
css_route: &str,
+ default_color_scheme: &str,
+ default_color_scheme_dark: &str,
) -> future::Ready<Result<HttpResponse, actix_web::Error>> {
errors::log_error_chain(description.to_string());
future::ok(
@@ -235,6 +250,8 @@ fn create_error_response(
!uses_random_route,
&favicon_route,
&css_route,
+ default_color_scheme,
+ default_color_scheme_dark,
)
.into_string(),
),
diff --git a/src/listing.rs b/src/listing.rs
index 322de73..755b026 100644
--- a/src/listing.rs
+++ b/src/listing.rs
@@ -152,6 +152,8 @@ pub fn directory_listing(
random_route: Option<String>,
favicon_route: String,
css_route: String,
+ default_color_scheme: &str,
+ default_color_scheme_dark: &str,
show_qrcode: bool,
upload_route: String,
tar_enabled: bool,
@@ -338,6 +340,8 @@ pub fn directory_listing(
false,
&favicon_route,
&css_route,
+ default_color_scheme,
+ default_color_scheme_dark,
)
.into_string(),
),
@@ -397,6 +401,8 @@ pub fn directory_listing(
&upload_route,
&favicon_route,
&css_route,
+ default_color_scheme,
+ default_color_scheme_dark,
&encoded_dir,
breadcrumbs,
tar_enabled,
diff --git a/src/main.rs b/src/main.rs
index 2886a2c..b947004 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -58,6 +58,12 @@ pub struct MiniserveConfig {
/// Randomly generated css route
pub css_route: String,
+ /// Default color scheme
+ pub default_color_scheme: String,
+
+ /// Default dark mode color scheme
+ pub default_color_scheme_dark: String,
+
/// The name of a directory index file to serve, like "index.html"
///
/// Normally, when miniserve serves a directory, it creates a listing for that directory.
@@ -285,6 +291,8 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
let random_route = conf.random_route.clone();
let favicon_route = conf.favicon_route.clone();
let css_route = conf.css_route.clone();
+ let default_color_scheme = conf.default_color_scheme.clone();
+ let default_color_scheme_dark = conf.default_color_scheme_dark.clone();
let show_qrcode = conf.show_qrcode;
let file_upload = conf.file_upload;
let tar_enabled = conf.tar_enabled;
@@ -315,6 +323,8 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
random_route.clone(),
favicon_route.clone(),
css_route.clone(),
+ &default_color_scheme,
+ &default_color_scheme_dark,
show_qrcode,
u_r.clone(),
tar_enabled,
@@ -329,6 +339,10 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
let favicon_route = conf.favicon_route.clone();
let css_route = conf.css_route.clone();
+
+ let default_color_scheme = conf.default_color_scheme.clone();
+ let default_color_scheme_dark = conf.default_color_scheme_dark.clone();
+
if let Some(serve_path) = serve_path {
if conf.file_upload {
// Allow file upload
@@ -340,6 +354,8 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
uses_random_route,
favicon_route.clone(),
css_route.clone(),
+ &default_color_scheme,
+ &default_color_scheme_dark,
)
})),
)
@@ -376,6 +392,8 @@ async fn error_404(req: HttpRequest) -> HttpResponse {
!uses_random_route,
&favicon_route,
&css_route,
+ &conf.default_color_scheme,
+ &conf.default_color_scheme_dark,
)
.into_string(),
)
diff --git a/src/renderer.rs b/src/renderer.rs
index 2ebe214..61e382e 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -20,6 +20,8 @@ pub fn page(
upload_route: &str,
favicon_route: &str,
css_route: &str,
+ default_color_scheme: &str,
+ default_color_scheme_dark: &str,
encoded_dir: &str,
breadcrumbs: Vec<Breadcrumb>,
tar_enabled: bool,
@@ -37,7 +39,7 @@ pub fn page(
(DOCTYPE)
html {
(page_header(&title_path, file_upload, favicon_route, css_route))
- body#drop-container {
+ body#drop-container.(format!("default_theme_{}", default_color_scheme)).(format!("default_theme_dark_{}", default_color_scheme_dark)) {
(PreEscaped(r#"
<script>
const body = document.body;
@@ -153,7 +155,7 @@ fn build_upload_action(
upload_action
}
-const THEMES: &[(&str, &str)] = &[
+const THEME_PICKER_CHOICES: &[(&str, &str)] = &[
("Default (light/dark)", "default"),
("Squirrel (light)", "squirrel"),
("Archlinux (dark)", "archlinux"),
@@ -161,6 +163,8 @@ const THEMES: &[(&str, &str)] = &[
("Monokai (dark)", "monokai"),
];
+pub const THEME_SLUGS: &[&str] = &["squirrel", "archlinux", "zenburn", "monokai"];
+
/// Partial: color scheme selector
fn color_scheme_selector(show_qrcode: bool) -> Markup {
html! {
@@ -180,7 +184,7 @@ fn color_scheme_selector(show_qrcode: bool) -> Markup {
"Change theme..."
}
ul.theme {
- @for color_scheme in THEMES {
+ @for color_scheme in THEME_PICKER_CHOICES {
li.(format!("theme_{}", color_scheme.1)) {
(color_scheme_link(color_scheme))
}
@@ -452,6 +456,8 @@ pub fn render_error(
display_back_link: bool,
favicon_route: &str,
css_route: &str,
+ default_color_scheme: &str,
+ default_color_scheme_dark: &str,
) -> Markup {
let link = if has_referer {
return_address.to_string()
@@ -463,7 +469,7 @@ pub fn render_error(
(DOCTYPE)
html {
(page_header(&error_code.to_string(), false, favicon_route, css_route))
- body {
+ body.(format!("default_theme_{}", default_color_scheme)).(format!("default_theme_dark_{}", default_color_scheme_dark)) {
div.error {
p { (error_code.to_string()) }
@for error in error_description.lines() {