From b018457e54c66862f163cb5aacbca71a3321c9ae Mon Sep 17 00:00:00 2001 From: Gaurav Date: Tue, 2 Aug 2022 20:44:10 -0400 Subject: [PATCH 1/8] Add support for readme rendering --- Cargo.lock | 18 ++++++++++++++++++ Cargo.toml | 2 ++ src/listing.rs | 8 +++++++- src/renderer.rs | 9 +++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 54b5b99f0..3d106ff75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1360,6 +1360,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "markdown" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef3aab6a1d529b112695f72beec5ee80e729cb45af58663ec902c8fac764ecdd" +dependencies = [ + "lazy_static", + "pipeline", + "regex", +] + [[package]] name = "markup5ever" version = "0.10.1" @@ -1462,6 +1473,7 @@ dependencies = [ "httparse", "libflate", "log", + "markdown", "maud", "mime", "nanoid", @@ -1761,6 +1773,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pipeline" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15b6607fa632996eb8a17c9041cb6071cb75ac057abd45dece578723ea8c7c0" + [[package]] name = "port_check" version = "0.1.5" diff --git a/Cargo.toml b/Cargo.toml index 6037d87be..4c91032be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,8 @@ tar = "0.4" thiserror = "1" yansi = "0.5" zip = { version = "0.6.2", default-features = false } +get_if_addrs = "0.5" +markdown = "0.3.0" [features] default = ["tls"] diff --git a/src/listing.rs b/src/listing.rs index 25f50faad..3c77c1498 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -232,6 +232,7 @@ pub fn directory_listing( } let mut entries: Vec = Vec::new(); + let mut readme: Option = None; for entry in dir.path.read_dir()? { if dir.is_visible(&entry) || conf.show_hidden { @@ -275,13 +276,17 @@ pub fn directory_listing( )); } else if metadata.is_file() { entries.push(Entry::new( - file_name, + file_name.clone(), EntryType::File, file_url, Some(ByteSize::b(metadata.len())), last_modification_date, symlink_dest, )); + // TODO: Pattern match, or user arg for readme name? + if file_name.to_lowercase() == "readme.md"{ + readme = Some(file_name); + } } } else { continue; @@ -372,6 +377,7 @@ pub fn directory_listing( HttpResponse::Ok().content_type(mime::TEXT_HTML_UTF_8).body( renderer::page( entries, + readme, is_root, query_params, breadcrumbs, diff --git a/src/renderer.rs b/src/renderer.rs index 75d2c716e..775d7c8e8 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -5,6 +5,7 @@ use clap::{crate_name, crate_version}; use maud::{html, Markup, PreEscaped, DOCTYPE}; use std::time::SystemTime; use strum::IntoEnumIterator; +use std::path::Path; use crate::auth::CurrentUser; use crate::listing::{Breadcrumb, Entry, QueryParameters, SortingMethod, SortingOrder}; @@ -13,6 +14,7 @@ use crate::{archive::ArchiveMethod, MiniserveConfig}; /// Renders the file listing pub fn page( entries: Vec, + readme: Option, is_root: bool, query_params: QueryParameters, breadcrumbs: Vec, @@ -165,6 +167,13 @@ pub fn page( } } } + @if readme.is_some() { + div { + h3 { (readme.as_ref().unwrap()) } + (PreEscaped + (markdown::file_to_html(Path::new(&readme.unwrap())).unwrap())); + } + } a.back href="#top" { (arrow_up()) } From bd6ae43592df50244c6fde84e27a7f51dbe7d77f Mon Sep 17 00:00:00 2001 From: Gaurav Date: Tue, 2 Aug 2022 21:45:56 -0400 Subject: [PATCH 2/8] Add `--readme` flag to cli --- src/args.rs | 4 ++++ src/config.rs | 4 ++++ src/listing.rs | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/args.rs b/src/args.rs index 687649de4..967465117 100644 --- a/src/args.rs +++ b/src/args.rs @@ -197,6 +197,10 @@ pub struct CliArgs { #[cfg(feature = "tls")] #[clap(long = "tls-key", requires = "tls-cert", value_hint = ValueHint::FilePath)] pub tls_key: Option, + + /// Enable readme redering in directories + #[clap(long = "readme")] + pub readme: bool, } /// Checks wether an interface is valid, i.e. it can be parsed into an IP address diff --git a/src/config.rs b/src/config.rs index ec7ec660f..9dddeb9a3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -123,6 +123,9 @@ pub struct MiniserveConfig { /// If enabled, display a wget command to recursively download the current directory pub show_wget_footer: bool, + /// If enabled, render the readme from the current directory + pub readme: bool, + /// If set, use provided rustls config for TLS #[cfg(feature = "tls")] pub tls_rustls_config: Option, @@ -256,6 +259,7 @@ impl MiniserveConfig { hide_version_footer: args.hide_version_footer, hide_theme_selector: args.hide_theme_selector, show_wget_footer: args.show_wget_footer, + readme: args.readme, tls_rustls_config: tls_rustls_server_config, }) } diff --git a/src/listing.rs b/src/listing.rs index 3c77c1498..458744c01 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -283,8 +283,8 @@ pub fn directory_listing( last_modification_date, symlink_dest, )); - // TODO: Pattern match, or user arg for readme name? - if file_name.to_lowercase() == "readme.md"{ + // TODO: Pattern match? + if conf.readme && file_name.to_lowercase() == "readme.md"{ readme = Some(file_name); } } From 03f798d71508cf0fe1856fce6e107229065c06cc Mon Sep 17 00:00:00 2001 From: Gaurav Date: Tue, 2 Aug 2022 23:07:36 -0400 Subject: [PATCH 3/8] Replace `markdown` by `comrak`; Render support for nested dirs * README.md will be rendered at currently visiting directory instead of just in the root. * Rendering is now done by comrak, which seems heavy but has a lot more features. --- Cargo.lock | 284 +++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 +- src/listing.rs | 8 +- src/renderer.rs | 13 ++- 4 files changed, 285 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d106ff75..eaa6c5dc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -397,6 +397,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -617,6 +626,26 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e769b5c8c8283982a987c6e948e540254f1058d5a74b8794914d4ef5fc2a24" +[[package]] +name = "comrak" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf1e432b302dc6236dd0db580d182ce520bb24af82d6462e2d7a5e0a31c50d" +dependencies = [ + "clap 2.34.0", + "entities", + "lazy_static", + "memchr", + "pest", + "pest_derive", + "regex", + "shell-words", + "syntect", + "typed-arena", + "unicode_categories", + "xdg", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -733,6 +762,26 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -754,6 +803,22 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "entities" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" + +[[package]] +name = "fancy-regex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6b8560a05112eb52f04b00e5d3790c0dd75d9d980eb8a122fb23b92a623ccf" +dependencies = [ + "bit-set", + "regex", +] + [[package]] name = "fastrand" version = "1.8.0" @@ -1291,6 +1356,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.129" @@ -1317,6 +1388,21 @@ dependencies = [ "rle-decode-fast", ] +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "local-channel" version = "0.1.3" @@ -1360,17 +1446,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -[[package]] -name = "markdown" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef3aab6a1d529b112695f72beec5ee80e729cb45af58663ec902c8fac764ecdd" -dependencies = [ - "lazy_static", - "pipeline", - "regex", -] - [[package]] name = "markup5ever" version = "0.10.1" @@ -1465,6 +1540,7 @@ dependencies = [ "clap 3.2.16", "clap_complete", "clap_mangen", + "comrak", "futures", "get_if_addrs", "grass", @@ -1473,7 +1549,6 @@ dependencies = [ "httparse", "libflate", "log", - "markdown", "maud", "mime", "nanoid", @@ -1610,6 +1685,28 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +[[package]] +name = "onig" +version = "6.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eb3502504c9c8b06634b38bfdda86a9a8cef6277f3dec4d8b17c115110dd2a3" +dependencies = [ + "bitflags", + "lazy_static", + "libc", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf3fbc9b931b6c9af85d219c7943c274a6ad26cff7488a2210215edd5f49bf8" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "os_str_bytes" version = "6.2.0" @@ -1660,6 +1757,50 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pest" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13570633aff33c6d22ce47dd566b10a3b9122c2fe9d8e7501895905be532b91" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3c567e5702efdc79fb18859ea74c3eb36e14c43da7b8c1f098a4ed6514ec7a0" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb32be5ee3bbdafa8c7a18b0a8a8d962b66cfa2ceee4037f49267a50ee821fe" +dependencies = [ + "once_cell", + "pest", + "sha-1", +] + [[package]] name = "phf" version = "0.8.0" @@ -1774,10 +1915,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "pipeline" -version = "0.5.0" +name = "pkg-config" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15b6607fa632996eb8a17c9041cb6071cb75ac057abd45dece578723ea8c7c0" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "plist" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" +dependencies = [ + "base64", + "indexmap", + "line-wrap", + "serde", + "time 0.3.11", + "xml-rs", +] [[package]] name = "port_check" @@ -1983,6 +2138,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.7", + "redox_syscall", + "thiserror", +] + [[package]] name = "regex" version = "1.6.0" @@ -2149,6 +2315,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + [[package]] name = "same-file" version = "1.0.6" @@ -2234,6 +2406,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha1" version = "0.10.1" @@ -2256,6 +2439,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -2381,6 +2570,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syntect" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b20815bbe80ee0be06e6957450a841185fcf690fe0178f14d77a05ce2caa031" +dependencies = [ + "bincode", + "bitflags", + "fancy-regex", + "flate2", + "fnv", + "lazy_static", + "lazycell", + "onig", + "plist", + "regex-syntax", + "serde", + "serde_derive", + "serde_json", + "walkdir", + "yaml-rust", +] + [[package]] name = "tar" version = "0.4.38" @@ -2621,12 +2833,24 @@ dependencies = [ "unchecked-index", ] +[[package]] +name = "typed-arena" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" + [[package]] name = "typenum" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "ucd-trie" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" + [[package]] name = "unchecked-index" version = "0.2.2" @@ -2669,6 +2893,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "untrusted" version = "0.7.1" @@ -2946,6 +3176,21 @@ dependencies = [ "libc", ] +[[package]] +name = "xdg" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6" +dependencies = [ + "dirs", +] + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + [[package]] name = "xml5ever" version = "0.16.2" @@ -2958,6 +3203,15 @@ dependencies = [ "time 0.1.44", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yansi" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 4c91032be..d22199a52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,7 @@ thiserror = "1" yansi = "0.5" zip = { version = "0.6.2", default-features = false } get_if_addrs = "0.5" -markdown = "0.3.0" +comrak = "0.14.0" [features] default = ["tls"] diff --git a/src/listing.rs b/src/listing.rs index 458744c01..436add928 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -232,7 +232,7 @@ pub fn directory_listing( } let mut entries: Vec = Vec::new(); - let mut readme: Option = None; + let mut readme: Option = None; for entry in dir.path.read_dir()? { if dir.is_visible(&entry) || conf.show_hidden { @@ -285,7 +285,11 @@ pub fn directory_listing( )); // TODO: Pattern match? if conf.readme && file_name.to_lowercase() == "readme.md"{ - readme = Some(file_name); + let file_path = conf.path.canonicalize().unwrap() + .join(base.as_os_str().to_str().unwrap() + .strip_prefix("/").unwrap()) + .join(&file_name); + readme = Some(file_path); } } } else { diff --git a/src/renderer.rs b/src/renderer.rs index 775d7c8e8..5fdd2bef1 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -3,9 +3,10 @@ use chrono::{DateTime, Utc}; use chrono_humanize::Humanize; use clap::{crate_name, crate_version}; use maud::{html, Markup, PreEscaped, DOCTYPE}; +use std::path::PathBuf; use std::time::SystemTime; use strum::IntoEnumIterator; -use std::path::Path; +use comrak::{markdown_to_html, ComrakOptions}; use crate::auth::CurrentUser; use crate::listing::{Breadcrumb, Entry, QueryParameters, SortingMethod, SortingOrder}; @@ -14,7 +15,7 @@ use crate::{archive::ArchiveMethod, MiniserveConfig}; /// Renders the file listing pub fn page( entries: Vec, - readme: Option, + readme: Option, is_root: bool, query_params: QueryParameters, breadcrumbs: Vec, @@ -169,9 +170,13 @@ pub fn page( } @if readme.is_some() { div { - h3 { (readme.as_ref().unwrap()) } + h3 { (readme.as_ref().unwrap().file_name().unwrap() + .to_string_lossy().to_string()) } (PreEscaped - (markdown::file_to_html(Path::new(&readme.unwrap())).unwrap())); + (markdown_to_html( + &std::fs::read_to_string(readme.unwrap()) + .unwrap_or_else(|_| "Cannot read File.".to_string()), + &ComrakOptions::default()))); } } a.back href="#top" { From f56840a4c04b18fcc6955d7105d32ec9bd6b01dd Mon Sep 17 00:00:00 2001 From: Gaurav Date: Wed, 3 Aug 2022 20:03:37 -0400 Subject: [PATCH 4/8] Satisfy cargo fmt --- src/config.rs | 2 +- src/listing.rs | 26 +++++++++++++++++--------- src/renderer.rs | 24 ++++++++++++------------ 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/config.rs b/src/config.rs index 9dddeb9a3..5bcbd625e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -259,7 +259,7 @@ impl MiniserveConfig { hide_version_footer: args.hide_version_footer, hide_theme_selector: args.hide_theme_selector, show_wget_footer: args.show_wget_footer, - readme: args.readme, + readme: args.readme, tls_rustls_config: tls_rustls_server_config, }) } diff --git a/src/listing.rs b/src/listing.rs index 436add928..42054ca3d 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -283,14 +283,22 @@ pub fn directory_listing( last_modification_date, symlink_dest, )); - // TODO: Pattern match? - if conf.readme && file_name.to_lowercase() == "readme.md"{ - let file_path = conf.path.canonicalize().unwrap() - .join(base.as_os_str().to_str().unwrap() - .strip_prefix("/").unwrap()) - .join(&file_name); - readme = Some(file_path); - } + // TODO: Pattern match? + if conf.readme && file_name.to_lowercase() == "readme.md" { + let file_path = conf + .path + .canonicalize() + .unwrap() + .join( + base.as_os_str() + .to_str() + .unwrap() + .strip_prefix('/') + .unwrap(), + ) + .join(&file_name); + readme = Some(file_path); + } } } else { continue; @@ -381,7 +389,7 @@ pub fn directory_listing( HttpResponse::Ok().content_type(mime::TEXT_HTML_UTF_8).body( renderer::page( entries, - readme, + readme, is_root, query_params, breadcrumbs, diff --git a/src/renderer.rs b/src/renderer.rs index 5fdd2bef1..3ce985bda 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -2,11 +2,11 @@ use actix_web::http::StatusCode; use chrono::{DateTime, Utc}; use chrono_humanize::Humanize; use clap::{crate_name, crate_version}; +use comrak::{markdown_to_html, ComrakOptions}; use maud::{html, Markup, PreEscaped, DOCTYPE}; use std::path::PathBuf; use std::time::SystemTime; use strum::IntoEnumIterator; -use comrak::{markdown_to_html, ComrakOptions}; use crate::auth::CurrentUser; use crate::listing::{Breadcrumb, Entry, QueryParameters, SortingMethod, SortingOrder}; @@ -168,17 +168,17 @@ pub fn page( } } } - @if readme.is_some() { - div { - h3 { (readme.as_ref().unwrap().file_name().unwrap() - .to_string_lossy().to_string()) } - (PreEscaped - (markdown_to_html( - &std::fs::read_to_string(readme.unwrap()) - .unwrap_or_else(|_| "Cannot read File.".to_string()), - &ComrakOptions::default()))); - } - } + @if readme.is_some() { + div { + h3 { (readme.as_ref().unwrap().file_name().unwrap() + .to_string_lossy().to_string()) } + (PreEscaped + (markdown_to_html( + &std::fs::read_to_string(readme.unwrap()) + .unwrap_or_else(|_| "Cannot read File.".to_string()), + &ComrakOptions::default()))); + } + } a.back href="#top" { (arrow_up()) } From 19ab9c632e4a12dd7c7c30f56317bf26cb0e3f2f Mon Sep 17 00:00:00 2001 From: Gaurav Date: Thu, 11 Aug 2022 21:46:56 -0400 Subject: [PATCH 5/8] Add `--readme` info and reformat --- Cargo.lock | 2 +- Cargo.toml | 1 - README.md | 4 ++++ src/args.rs | 4 ++-- src/listing.rs | 1 - src/renderer.rs | 19 ++++++++++--------- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eaa6c5dc3..b1bc4acd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1930,7 +1930,7 @@ dependencies = [ "indexmap", "line-wrap", "serde", - "time 0.3.11", + "time 0.3.13", "xml-rs", ] diff --git a/Cargo.toml b/Cargo.toml index d22199a52..08a0f0c65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,6 @@ tar = "0.4" thiserror = "1" yansi = "0.5" zip = { version = "0.6.2", default-features = false } -get_if_addrs = "0.5" comrak = "0.14.0" [features] diff --git a/README.md b/README.md index 4f477b2df..49bd51b6c 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ Some mobile browsers like Firefox on Android will offer to open the camera app w - Shell completions - Sane and secure defaults - TLS (for supported architectures) +- Supports README.md rendering like on GitHub ## Usage @@ -204,6 +205,9 @@ Some mobile browsers like Firefox on Android will offer to open the camera app w --random-route Generate a random 6-hexdigit route + --readme + Enable README.md redering in directories + --route-prefix Use a specific route prefix diff --git a/src/args.rs b/src/args.rs index 967465117..dd96f05d0 100644 --- a/src/args.rs +++ b/src/args.rs @@ -198,8 +198,8 @@ pub struct CliArgs { #[clap(long = "tls-key", requires = "tls-cert", value_hint = ValueHint::FilePath)] pub tls_key: Option, - /// Enable readme redering in directories - #[clap(long = "readme")] + /// Enable README.md redering in directories + #[clap(long)] pub readme: bool, } diff --git a/src/listing.rs b/src/listing.rs index 42054ca3d..1c017b086 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -283,7 +283,6 @@ pub fn directory_listing( last_modification_date, symlink_dest, )); - // TODO: Pattern match? if conf.readme && file_name.to_lowercase() == "readme.md" { let file_path = conf .path diff --git a/src/renderer.rs b/src/renderer.rs index 3ce985bda..abf605324 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -12,6 +12,7 @@ use crate::auth::CurrentUser; use crate::listing::{Breadcrumb, Entry, QueryParameters, SortingMethod, SortingOrder}; use crate::{archive::ArchiveMethod, MiniserveConfig}; +#[allow(clippy::too_many_arguments)] /// Renders the file listing pub fn page( entries: Vec, @@ -169,15 +170,15 @@ pub fn page( } } @if readme.is_some() { - div { - h3 { (readme.as_ref().unwrap().file_name().unwrap() - .to_string_lossy().to_string()) } - (PreEscaped - (markdown_to_html( - &std::fs::read_to_string(readme.unwrap()) - .unwrap_or_else(|_| "Cannot read File.".to_string()), - &ComrakOptions::default()))); - } + div { + h3 { (readme.as_ref().unwrap().file_name().unwrap() + .to_string_lossy().to_string()) } + (PreEscaped + (markdown_to_html( + &std::fs::read_to_string(readme.unwrap()) + .unwrap_or_else(|_| "Cannot read File.".to_string()), + &ComrakOptions::default()))); + } } a.back href="#top" { (arrow_up()) From 04ec70e10400642df96c9ffd4eb4daf19cf44df9 Mon Sep 17 00:00:00 2001 From: Gaurav Date: Sat, 13 Aug 2022 21:09:02 -0400 Subject: [PATCH 6/8] Make Readme struct --- src/listing.rs | 61 +++++++++++++++++++++++++++++++++++++------------ src/renderer.rs | 17 ++++---------- 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/listing.rs b/src/listing.rs index 1c017b086..3a54118b5 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -7,6 +7,7 @@ use actix_web::dev::ServiceResponse; use actix_web::web::Query; use actix_web::{HttpMessage, HttpRequest, HttpResponse}; use bytesize::ByteSize; +use comrak::{markdown_to_html, ComrakOptions}; use percent_encoding::{percent_decode_str, utf8_percent_encode}; use qrcodegen::{QrCode, QrCodeEcc}; use serde::Deserialize; @@ -146,6 +147,50 @@ impl Breadcrumb { } } +/// Readme file information +pub struct Readme { + pub render: bool, + pub path: Option, + pub filename: Option, + pub contents: Option, +} + +impl Readme { + fn blank() -> Self { + Readme { + render: false, + path: None, + filename: None, + contents: None, + } + } + + fn new(root: PathBuf, base: &Path, filename: String) -> Self { + let file_path = root + .canonicalize() + .unwrap() + .join( + base.as_os_str() + .to_str() + .unwrap() + .strip_prefix('/') + .unwrap(), + ) + .join(&filename); + let contents = markdown_to_html( + &std::fs::read_to_string(&file_path) + .unwrap_or_else(|_| "Cannot read File.".to_string()), + &ComrakOptions::default(), + ); + Readme { + render: true, + path: Some(file_path), + filename: Some(filename), + contents: Some(contents), + } + } +} + pub async fn file_handler(req: HttpRequest) -> actix_web::Result { let path = &req.app_data::().unwrap().path; actix_files::NamedFile::open(path).map_err(Into::into) @@ -232,7 +277,7 @@ pub fn directory_listing( } let mut entries: Vec = Vec::new(); - let mut readme: Option = None; + let mut readme = Readme::blank(); for entry in dir.path.read_dir()? { if dir.is_visible(&entry) || conf.show_hidden { @@ -284,19 +329,7 @@ pub fn directory_listing( symlink_dest, )); if conf.readme && file_name.to_lowercase() == "readme.md" { - let file_path = conf - .path - .canonicalize() - .unwrap() - .join( - base.as_os_str() - .to_str() - .unwrap() - .strip_prefix('/') - .unwrap(), - ) - .join(&file_name); - readme = Some(file_path); + readme = Readme::new(conf.path.clone(), base, file_name) } } } else { diff --git a/src/renderer.rs b/src/renderer.rs index abf605324..bafddaf68 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -2,21 +2,19 @@ use actix_web::http::StatusCode; use chrono::{DateTime, Utc}; use chrono_humanize::Humanize; use clap::{crate_name, crate_version}; -use comrak::{markdown_to_html, ComrakOptions}; use maud::{html, Markup, PreEscaped, DOCTYPE}; -use std::path::PathBuf; use std::time::SystemTime; use strum::IntoEnumIterator; use crate::auth::CurrentUser; -use crate::listing::{Breadcrumb, Entry, QueryParameters, SortingMethod, SortingOrder}; +use crate::listing::{Breadcrumb, Entry, QueryParameters, Readme, SortingMethod, SortingOrder}; use crate::{archive::ArchiveMethod, MiniserveConfig}; #[allow(clippy::too_many_arguments)] /// Renders the file listing pub fn page( entries: Vec, - readme: Option, + readme: Readme, is_root: bool, query_params: QueryParameters, breadcrumbs: Vec, @@ -169,15 +167,10 @@ pub fn page( } } } - @if readme.is_some() { + @if readme.render { div { - h3 { (readme.as_ref().unwrap().file_name().unwrap() - .to_string_lossy().to_string()) } - (PreEscaped - (markdown_to_html( - &std::fs::read_to_string(readme.unwrap()) - .unwrap_or_else(|_| "Cannot read File.".to_string()), - &ComrakOptions::default()))); + h3 { (readme.filename.unwrap()) } + (PreEscaped (readme.contents.unwrap())); } } a.back href="#top" { From ebf5337ff1075aa9138f9d02ab9c52af41c8890b Mon Sep 17 00:00:00 2001 From: Gaurav Date: Sat, 13 Aug 2022 22:00:41 -0400 Subject: [PATCH 7/8] Edit Readme struct to remove render bool --- src/listing.rs | 27 ++++++++------------------- src/renderer.rs | 8 ++++---- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/listing.rs b/src/listing.rs index 3a54118b5..6f9e485b5 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -149,22 +149,12 @@ impl Breadcrumb { /// Readme file information pub struct Readme { - pub render: bool, - pub path: Option, - pub filename: Option, - pub contents: Option, + pub path: PathBuf, + pub filename: String, + pub contents: String, } impl Readme { - fn blank() -> Self { - Readme { - render: false, - path: None, - filename: None, - contents: None, - } - } - fn new(root: PathBuf, base: &Path, filename: String) -> Self { let file_path = root .canonicalize() @@ -183,10 +173,9 @@ impl Readme { &ComrakOptions::default(), ); Readme { - render: true, - path: Some(file_path), - filename: Some(filename), - contents: Some(contents), + path: file_path, + filename, + contents, } } } @@ -277,7 +266,7 @@ pub fn directory_listing( } let mut entries: Vec = Vec::new(); - let mut readme = Readme::blank(); + let mut readme: Option = None; for entry in dir.path.read_dir()? { if dir.is_visible(&entry) || conf.show_hidden { @@ -329,7 +318,7 @@ pub fn directory_listing( symlink_dest, )); if conf.readme && file_name.to_lowercase() == "readme.md" { - readme = Readme::new(conf.path.clone(), base, file_name) + readme = Some(Readme::new(conf.path.clone(), base, file_name)); } } } else { diff --git a/src/renderer.rs b/src/renderer.rs index bafddaf68..1e92cbe05 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -14,7 +14,7 @@ use crate::{archive::ArchiveMethod, MiniserveConfig}; /// Renders the file listing pub fn page( entries: Vec, - readme: Readme, + readme: Option, is_root: bool, query_params: QueryParameters, breadcrumbs: Vec, @@ -167,10 +167,10 @@ pub fn page( } } } - @if readme.render { + @if readme.is_some() { div { - h3 { (readme.filename.unwrap()) } - (PreEscaped (readme.contents.unwrap())); + h3 { (readme.as_ref().unwrap().filename) } + (PreEscaped (readme.unwrap().contents)); } } a.back href="#top" { From 02dee7561ba11135c3a265f8cba654c55589bb3d Mon Sep 17 00:00:00 2001 From: Gaurav Date: Sat, 13 Aug 2022 23:53:28 -0400 Subject: [PATCH 8/8] Correct Spelling --- README.md | 2 +- src/args.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 49bd51b6c..a44cdaee2 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ Some mobile browsers like Firefox on Android will offer to open the camera app w Generate a random 6-hexdigit route --readme - Enable README.md redering in directories + Enable README.md rendering in directories --route-prefix Use a specific route prefix diff --git a/src/args.rs b/src/args.rs index dd96f05d0..a76925656 100644 --- a/src/args.rs +++ b/src/args.rs @@ -198,7 +198,7 @@ pub struct CliArgs { #[clap(long = "tls-key", requires = "tls-cert", value_hint = ValueHint::FilePath)] pub tls_key: Option, - /// Enable README.md redering in directories + /// Enable README.md rendering in directories #[clap(long)] pub readme: bool, }