aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--data/style.scss16
-rw-r--r--src/args.rs4
-rw-r--r--src/config.rs4
-rw-r--r--src/listing.rs20
-rw-r--r--src/main.rs2
-rw-r--r--src/renderer.rs31
-rw-r--r--tests/serve_request.rs19
7 files changed, 69 insertions, 27 deletions
diff --git a/data/style.scss b/data/style.scss
index 0a69222..7e63751 100644
--- a/data/style.scss
+++ b/data/style.scss
@@ -95,11 +95,18 @@ a.file:hover {
color: var(--file_link_color);
}
+a.symlink,
+a.symlink:visited {
+ font-weight: bold;
+ color: var(--symlink_color);
+}
+
.symlink-symbol::after {
content: "⇢";
display: inline-block;
border: 1px solid;
margin-left: 0.5rem;
+ margin-right: 0.5rem;
border-radius: 0.2rem;
padding: 0 0.1rem;
}
@@ -276,11 +283,6 @@ td.date-cell {
color: var(--date_text_color);
}
-.file-entry {
- display: flex;
- justify-content: space-between;
-}
-
span.size {
border-radius: 1rem;
background: var(--size_background_color);
@@ -532,6 +534,7 @@ th span.active span {
--directory_link_color_visited: #9b1985;
--file_link_color: #0086b3;
--file_link_color_visited: #974ec2;
+ --symlink_color: #ADD8E6;
--table_background: #ffffff;
--table_text_color: #323232;
--table_header_background: #323232;
@@ -578,6 +581,7 @@ th span.active span {
--directory_link_color_visited: #0388f4;
--file_link_color: #ea95ff;
--file_link_color_visited: #a595ff;
+ --symlink_color: #66d9ef;
--table_background: #353946;
--table_text_color: #eeeeee;
--table_header_background: #5294e2;
@@ -624,6 +628,7 @@ th span.active span {
--directory_link_color_visited: #ebc390;
--file_link_color: #87d6d5;
--file_link_color_visited: #a7b9ec;
+ --symlink_color: #11a8cd;
--table_background: #4a4949;
--table_text_color: #efefef;
--table_header_background: #7f9f7f;
@@ -670,6 +675,7 @@ th span.active span {
--directory_link_color_visited: #bc39a7;
--file_link_color: #a6e22e;
--file_link_color_visited: #4cb936;
+ --symlink_color: #29b8db;
--table_background: #3b3a32;
--table_text_color: #f8f8f0;
--table_header_background: #75715e;
diff --git a/src/args.rs b/src/args.rs
index 9569ca3..5467573 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -135,6 +135,10 @@ pub struct CliArgs {
)]
pub header: Vec<HeaderMap>,
+ /// Show symlink info
+ #[clap(short = 'l', long = "show-symlink-info")]
+ pub show_symlink_info: bool,
+
/// Hide version footer
#[clap(short = 'F', long = "hide-version-footer")]
pub hide_version_footer: bool,
diff --git a/src/config.rs b/src/config.rs
index e47ffc1..86fe314 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -95,6 +95,9 @@ pub struct MiniserveConfig {
/// If specified, header will be added
pub header: Vec<HeaderMap>,
+ /// If specified, symlink destination will be shown
+ pub show_symlink_info: bool,
+
/// If enabled, version footer is hidden
pub hide_version_footer: bool,
@@ -187,6 +190,7 @@ impl MiniserveConfig {
dirs_first: args.dirs_first,
title: args.title,
header: args.header,
+ show_symlink_info: args.show_symlink_info,
hide_version_footer: args.hide_version_footer,
tls_rustls_config: tls_rustls_server_config,
})
diff --git a/src/listing.rs b/src/listing.rs
index 33a0342..8147113 100644
--- a/src/listing.rs
+++ b/src/listing.rs
@@ -84,9 +84,6 @@ pub struct Entry {
/// Type of the entry
pub entry_type: EntryType,
- /// Entry is symlink. Not mutually exclusive with entry_type
- pub is_symlink: bool,
-
/// URL of the entry
pub link: String,
@@ -95,24 +92,27 @@ pub struct Entry {
/// Last modification date
pub last_modification_date: Option<SystemTime>,
+
+ /// Path of symlink pointed to
+ pub symlink_info: Option<String>,
}
impl Entry {
fn new(
name: String,
entry_type: EntryType,
- is_symlink: bool,
link: String,
size: Option<bytesize::ByteSize>,
last_modification_date: Option<SystemTime>,
+ symlink_info: Option<String>,
) -> Self {
Entry {
name,
entry_type,
- is_symlink,
link,
size,
last_modification_date,
+ symlink_info,
}
}
@@ -168,6 +168,7 @@ pub fn directory_listing(
zip_enabled: bool,
dirs_first: bool,
hide_version_footer: bool,
+ show_symlink_info: bool,
title: Option<String>,
) -> io::Result<ServiceResponse> {
use actix_web::dev::BodyEncoding;
@@ -252,6 +253,11 @@ pub fn directory_listing(
}
res => (false, res),
};
+ let symlink_dest = if is_symlink && show_symlink_info {
+ Some(std::fs::read_link(entry.path())?)
+ } else {
+ None
+ };
let file_url = base
.join(&utf8_percent_encode(&file_name, PATH_SEGMENT).to_string())
.to_string_lossy()
@@ -271,19 +277,19 @@ pub fn directory_listing(
entries.push(Entry::new(
file_name,
EntryType::Directory,
- is_symlink,
file_url,
None,
last_modification_date,
+ symlink_dest.and_then(|s| s.into_os_string().into_string().ok()),
));
} else if metadata.is_file() {
entries.push(Entry::new(
file_name,
EntryType::File,
- is_symlink,
file_url,
Some(ByteSize::b(metadata.len())),
last_modification_date,
+ symlink_dest.and_then(|s| s.into_os_string().into_string().ok()),
));
}
} else {
diff --git a/src/main.rs b/src/main.rs
index 882fd08..5f68cd2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -315,6 +315,7 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
let zip_enabled = conf.zip_enabled;
let dirs_first = conf.dirs_first;
let hide_version_footer = conf.hide_version_footer;
+ let cmd_enable_symlink_dest = conf.show_symlink_info;
let title = conf.title.clone();
if path.is_file() {
@@ -353,6 +354,7 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
zip_enabled,
dirs_first,
hide_version_footer,
+ cmd_enable_symlink_dest,
title.clone(),
)
})
diff --git a/src/renderer.rs b/src/renderer.rs
index 901bf66..3360504 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -328,24 +328,33 @@ fn entry_row(
td {
p {
@if entry.is_dir() {
- a.directory href=(parametrized_link(&entry.link, sort_method, sort_order)) {
- (entry.name) "/"
- @if entry.is_symlink {
+ @if let Some(symlink_dest) = entry.symlink_info {
+ a.symlink href=(parametrized_link(&entry.link, sort_method, sort_order)) {
+ (entry.name) "/"
span.symlink-symbol { }
+ a.directory {(symlink_dest) "/"}
+ }
+ }@else {
+ a.directory href=(parametrized_link(&entry.link, sort_method, sort_order)) {
+ (entry.name) "/"
}
}
} @else if entry.is_file() {
- div.file-entry {
+ @if let Some(symlink_dest) = entry.symlink_info {
+ a.symlink href=(&entry.link) {
+ (entry.name)
+ span.symlink-symbol { }
+ a.file {(symlink_dest)}
+ }
+ }@else {
a.file href=(&entry.link) {
(entry.name)
- @if entry.is_symlink {
- span.symlink-symbol { }
- }
}
- @if let Some(size) = entry.size {
- span.mobile-info.size {
- (size)
- }
+ }
+
+ @if let Some(size) = entry.size {
+ span.mobile-info.size {
+ (size)
}
}
}
diff --git a/tests/serve_request.rs b/tests/serve_request.rs
index bbbb7d9..ddf0471 100644
--- a/tests/serve_request.rs
+++ b/tests/serve_request.rs
@@ -123,10 +123,12 @@ fn serves_requests_no_hidden_files_without_flag(server: TestServer) -> Result<()
}
#[rstest]
-#[case(true, server(&["--no-symlinks"]))]
-#[case(false, server(None::<&str>))]
+#[case(true, false, server(&["--no-symlinks"]))]
+#[case(true, true, server(&["--no-symlinks", "--show-symlink-info"]))]
+#[case(false, false, server(None::<&str>))]
fn serves_requests_symlinks(
#[case] no_symlinks: bool,
+ #[case] show_symlink_info: bool,
#[case] server: TestServer,
) -> Result<(), Error> {
let files = &["symlink-file.html"];
@@ -154,6 +156,9 @@ fn serves_requests_symlinks(
.find(|x: &Node| x.name().unwrap_or_default() == "a" && x.text() == entry)
.next();
assert_eq!(node.is_none(), no_symlinks);
+ if node.is_some() && show_symlink_info {
+ assert_eq!(node.unwrap().attr("class").unwrap(), "symlink");
+ }
if no_symlinks {
continue;
}
@@ -162,9 +167,15 @@ fn serves_requests_symlinks(
assert_eq!(node.attr("href").unwrap().strip_prefix("/").unwrap(), entry);
reqwest::blocking::get(server.url().join(&entry)?)?.error_for_status()?;
if entry.ends_with("/") {
- assert_eq!(node.attr("class").unwrap(), "directory");
+ let node = parsed
+ .find(|x: &Node| x.name().unwrap_or_default() == "a" && x.text() == DIRECTORIES[0])
+ .next();
+ assert_eq!(node.unwrap().attr("class").unwrap(), "directory");
} else {
- assert_eq!(node.attr("class").unwrap(), "file");
+ let node = parsed
+ .find(|x: &Node| x.name().unwrap_or_default() == "a" && x.text() == FILES[0])
+ .next();
+ assert_eq!(node.unwrap().attr("class").unwrap(), "file");
}
}
for &entry in broken {