implement visitors count macro for each directory index

This commit is contained in:
yggverse 2025-06-28 18:13:17 +03:00
parent 450bbe60f3
commit 56830be4a9
7 changed files with 35 additions and 19 deletions

View file

@ -83,7 +83,7 @@ nexy -p /path/to/public_dir
* this template file expects pattern and cannot be in binary format
**Patterns** * `{list}` - entries list for the current directory
**Patterns** * `{list}` - entries list for the current directory * `{hosts}` - unique visitors count * `{hits}` - requests count
--list-dir-show-count
Show files count in dir (as the alternative text for navigation links)

View file

@ -73,6 +73,8 @@ pub struct Config {
///
/// **Patterns**
/// * `{list}` - entries list for the current directory
/// * `{hosts}` - unique visitors count
/// * `{hits}` - requests count
#[arg(long)]
pub template_index: Option<String>,

View file

@ -8,6 +8,6 @@ pub enum Response<'a> {
NotFound(&'a str),
/// Includes bytes array
File(&'a [u8]),
/// Includes bytes array + public root directory status
Directory(String, bool),
/// Includes query, list + is public root directory status
Directory(&'a str, String, bool),
}

View file

@ -70,15 +70,19 @@ impl Connection {
fn response(&mut self, response: Response) -> usize {
let bytes = match response {
Response::File(b) => b,
Response::Directory(ref s, is_root) => {
Response::Directory(q, ref s, is_root) => {
&if is_root {
self.session.template.welcome(
Some(s),
Some(self.session.request.count()),
Some(self.session.request.total()),
Some(self.session.request.total(None)),
)
} else {
self.session.template.index(Some(s))
self.session.template.index(
Some(s),
Some(self.session.request.count()),
Some(self.session.request.total(Some(q))),
)
}
}
Response::InternalServerError(e) => {

View file

@ -60,7 +60,7 @@ impl Public {
match fs::metadata(&p) {
Ok(t) => match (t.is_dir(), t.is_file()) {
(true, _) => callback(match self.list(&p) {
Ok(l) => Response::Directory(l, p == self.public_dir),
Ok(list) => Response::Directory(query, list, p == self.public_dir),
Err(e) => Response::InternalServerError(e.to_string()),
}),
(_, true) => match fs::File::open(p) {

View file

@ -37,15 +37,22 @@ impl Request {
}
}
pub fn total(&self) -> usize {
if let Some(ref this) = self.0 {
pub fn total(&self, query_prefix: Option<&str>) -> usize {
let mut t = 0;
for c in this.read().unwrap().values() {
t += c.len()
if let Some(ref this) = self.0 {
for queries in this.read().unwrap().values() {
match query_prefix {
Some(p) => {
for q in queries {
if q.value.starts_with(p) {
t += 1
}
}
}
None => t += queries.len(),
}
}
}
t
} else {
0
}
}
}

View file

@ -16,7 +16,7 @@ impl Template {
},
index: match config.template_index {
Some(ref p) => read_to_string(p)?,
None => "{list}".into(),
None => "{list}\n\n👁 {hosts} / {hits}".into(),
},
internal_server_error: match config.template_internal_server_error {
Some(ref p) => read(p)?,
@ -37,9 +37,11 @@ impl Template {
&self.access_denied
}
pub fn index(&self, list: Option<&str>) -> Vec<u8> {
pub fn index(&self, list: Option<&str>, hosts: Option<usize>, hits: Option<usize>) -> Vec<u8> {
self.index
.replace("{list}", list.unwrap_or_default())
.replace("{hosts}", &format_count(hosts))
.replace("{hits}", &format_count(hits))
.into()
}
@ -57,9 +59,6 @@ impl Template {
hosts: Option<usize>,
hits: Option<usize>,
) -> Vec<u8> {
fn format_count(v: Option<usize>) -> String {
v.map_or(String::new(), |c| c.to_string())
}
self.welcome
.replace("{list}", list.unwrap_or_default())
.replace("{hosts}", &format_count(hosts))
@ -67,3 +66,7 @@ impl Template {
.into()
}
}
fn format_count(v: Option<usize>) -> String {
v.map_or(String::new(), |c| c.to_string())
}