mirror of
https://github.com/svenstaro/miniserve
synced 2024-07-08 20:05:56 +00:00
Set default sorting order and method with arguments
This commit is contained in:
parent
9bd740b2d0
commit
e5e3ad2fed
12
README.md
12
README.md
|
@ -210,6 +210,18 @@ Options:
|
|||
|
||||
[env: MINISERVE_HIDDEN=]
|
||||
|
||||
-S, --default-sorting-method
|
||||
Default sort method for file list
|
||||
|
||||
[env: MINISERVE_DEFAULT_SORTING_METHOD=]
|
||||
[possible values: name, date, size]
|
||||
|
||||
-O, --default-sorting-order
|
||||
Default sort order for file list
|
||||
|
||||
[env: MINISERVE_DEFAULT_SORTING_ORDER=]
|
||||
[possible values: asc, desc]
|
||||
|
||||
-c, --color-scheme <COLOR_SCHEME>
|
||||
Default color scheme
|
||||
|
||||
|
|
20
src/args.rs
20
src/args.rs
|
@ -113,6 +113,26 @@ pub struct CliArgs {
|
|||
#[arg(short = 'H', long = "hidden", env = "MINISERVE_HIDDEN")]
|
||||
pub hidden: bool,
|
||||
|
||||
/// Default sorting method for file list
|
||||
#[arg(
|
||||
short = 'S',
|
||||
long = "default-sorting-method",
|
||||
default_value = "",
|
||||
ignore_case = true,
|
||||
env = "MINISERVE_DEFAULT_SORTING_METHOD"
|
||||
)]
|
||||
pub default_sorting_method: String,
|
||||
|
||||
/// Default sorting order for file list
|
||||
#[arg(
|
||||
short = 'O',
|
||||
long = "default-sorting-order",
|
||||
default_value = "",
|
||||
ignore_case = true,
|
||||
env = "MINISERVE_DEFAULT_SORTING_ORDER"
|
||||
)]
|
||||
pub default_sorting_order: String,
|
||||
|
||||
/// Default color scheme
|
||||
#[arg(
|
||||
short = 'c',
|
||||
|
|
|
@ -15,6 +15,7 @@ use crate::{
|
|||
args::{parse_auth, CliArgs, MediaType},
|
||||
auth::RequiredAuth,
|
||||
file_utils::sanitize_path,
|
||||
listing::{SortingMethod, SortingOrder},
|
||||
renderer::ThemeSlug,
|
||||
};
|
||||
|
||||
|
@ -50,6 +51,12 @@ pub struct MiniserveConfig {
|
|||
/// Show hidden files
|
||||
pub show_hidden: bool,
|
||||
|
||||
/// Default sorting method
|
||||
pub default_sorting_method: Option<SortingMethod>,
|
||||
|
||||
/// Default sorting order
|
||||
pub default_sorting_order: Option<SortingOrder>,
|
||||
|
||||
/// Route prefix; Either empty or prefixed with slash
|
||||
pub route_prefix: String,
|
||||
|
||||
|
@ -265,6 +272,24 @@ impl MiniserveConfig {
|
|||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
|
||||
let default_sorting_method: Option<SortingMethod> = match args
|
||||
.default_sorting_method
|
||||
.to_owned()
|
||||
.parse::<SortingMethod>()
|
||||
{
|
||||
Ok(value) => Some(value),
|
||||
Err(_) => None,
|
||||
};
|
||||
|
||||
let default_sorting_order: Option<SortingOrder> = match args
|
||||
.default_sorting_order
|
||||
.to_owned()
|
||||
.parse::<SortingOrder>()
|
||||
{
|
||||
Ok(value) => Some(value),
|
||||
Err(_) => None,
|
||||
};
|
||||
|
||||
Ok(MiniserveConfig {
|
||||
verbose: args.verbose,
|
||||
path: args.path.unwrap_or_else(|| PathBuf::from(".")),
|
||||
|
@ -274,6 +299,8 @@ impl MiniserveConfig {
|
|||
path_explicitly_chosen,
|
||||
no_symlinks: args.no_symlinks,
|
||||
show_hidden: args.hidden,
|
||||
default_sorting_method,
|
||||
default_sorting_order,
|
||||
route_prefix,
|
||||
favicon_route,
|
||||
css_route,
|
||||
|
|
|
@ -223,7 +223,7 @@ pub fn directory_listing(
|
|||
res
|
||||
};
|
||||
|
||||
let query_params = extract_query_parameters(req);
|
||||
let mut query_params = extract_query_parameters(req);
|
||||
|
||||
let mut entries: Vec<Entry> = Vec::new();
|
||||
let mut readme: Option<(String, String)> = None;
|
||||
|
@ -299,6 +299,14 @@ pub fn directory_listing(
|
|||
}
|
||||
}
|
||||
|
||||
if query_params.sort.is_none() {
|
||||
query_params.sort = conf.default_sorting_method
|
||||
}
|
||||
|
||||
if query_params.order.is_none() {
|
||||
query_params.order = conf.default_sorting_order
|
||||
}
|
||||
|
||||
match query_params.sort.unwrap_or(SortingMethod::Name) {
|
||||
SortingMethod::Name => entries.sort_by(|e1, e2| {
|
||||
alphanumeric_sort::compare_str(e1.name.to_lowercase(), e2.name.to_lowercase())
|
||||
|
@ -319,7 +327,7 @@ pub fn directory_listing(
|
|||
}),
|
||||
};
|
||||
|
||||
if let Some(SortingOrder::Descending) = query_params.order {
|
||||
if let Some(SortingOrder::Ascending) = query_params.order {
|
||||
entries.reverse()
|
||||
}
|
||||
|
||||
|
|
|
@ -459,7 +459,7 @@ fn build_link(
|
|||
) -> Markup {
|
||||
let mut link = format!("?sort={name}&order=asc");
|
||||
let mut help = format!("Sort by {name} in ascending order");
|
||||
let mut chevron = chevron_up();
|
||||
let mut chevron = chevron_down();
|
||||
let mut class = "";
|
||||
|
||||
if let Some(method) = sort_method {
|
||||
|
@ -469,7 +469,7 @@ fn build_link(
|
|||
if order.to_string() == "asc" {
|
||||
link = format!("?sort={name}&order=desc");
|
||||
help = format!("Sort by {name} in descending order");
|
||||
chevron = chevron_down();
|
||||
chevron = chevron_up();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
mod fixtures;
|
||||
mod utils;
|
||||
|
||||
use fixtures::{server, Error, TestServer, DEEPLY_NESTED_FILE, DIRECTORIES};
|
||||
use fixtures::{server, Error, TestServer, FILES, DEEPLY_NESTED_FILE, DIRECTORIES};
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
use rstest::rstest;
|
||||
use select::document::Document;
|
||||
use std::process::{Command, Stdio};
|
||||
use utils::get_link_from_text;
|
||||
use utils::get_link_hrefs_from_text_with_prefix;
|
||||
|
||||
#[rstest(
|
||||
input,
|
||||
|
@ -147,3 +148,30 @@ fn can_navigate_using_breadcrumbs(
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case(server(&["--default-sorting-method", "date", "--default-sorting-order", "desc"]))]
|
||||
#[case(server(&["--default-sorting-method", "date", "--default-sorting-order", "asc"]))]
|
||||
/// We can specify the default sorting order
|
||||
fn can_specify_default_sorting_order(#[case] server: TestServer) -> Result<(), Error> {
|
||||
let slash = String::from("/");
|
||||
let base_url = server.url();
|
||||
let nested_url = base_url.join(&slash)?;
|
||||
|
||||
let resp = reqwest::blocking::get(nested_url.as_str())?;
|
||||
let body = resp.error_for_status()?;
|
||||
let parsed = Document::from_read(body)?;
|
||||
|
||||
let links = get_link_hrefs_from_text_with_prefix(&parsed, "/");
|
||||
let first_created_file = slash + FILES.first().unwrap();
|
||||
|
||||
if links.first().unwrap() == &first_created_file {
|
||||
assert_eq!("/very/?sort=date&order=asc", links.last().unwrap());
|
||||
}
|
||||
|
||||
if links.last().unwrap() == &first_created_file {
|
||||
assert_eq!("/very/?sort=date&order=desc", links.first().unwrap());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -12,3 +12,19 @@ pub fn get_link_from_text(document: &Document, text: &str) -> Option<String> {
|
|||
.next()?;
|
||||
Some(a_elem.attr("href")?.to_string())
|
||||
}
|
||||
|
||||
/// Return the href attributes of all links that start with the specified prefix `text`.
|
||||
pub fn get_link_hrefs_from_text_with_prefix(document: &Document, text: &str) -> Vec<String> {
|
||||
let mut vec: Vec<String> = Vec::new();
|
||||
|
||||
let a_elem = document.find(Name("a"));
|
||||
|
||||
for element in a_elem {
|
||||
let str = element.attr("href").unwrap_or("");
|
||||
if str.to_string().starts_with(text) {
|
||||
vec.push(str.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user