parent
847008825f
commit
634706beec
3 changed files with 104 additions and 40 deletions
|
@ -60,7 +60,7 @@ impl Domain {
|
|||
Document::new(&self.name, path, self.dir.parent().unwrap().to_path_buf())
|
||||
}
|
||||
|
||||
pub fn paths(&self, path: &str) -> Vec<PathEntry> {
|
||||
pub fn paths(&self, path: &str) -> (Vec<PathEntry>, bool) {
|
||||
let mut base_path = self.dir.clone();
|
||||
|
||||
for p in path.split('/') {
|
||||
|
@ -71,44 +71,31 @@ impl Domain {
|
|||
|
||||
let mut ret = Vec::new();
|
||||
|
||||
let mut is_doc = false;
|
||||
|
||||
for entry in dir_content {
|
||||
let url_path = format!("{path}/{entry}");
|
||||
let is_doc = read_dir(&base_path.join(entry))
|
||||
.into_iter()
|
||||
.any(|x| x.starts_with("index_") && x.ends_with(".html"));
|
||||
if is_doc {
|
||||
ret.push(PathEntry::Document(Document::new(
|
||||
&self.name,
|
||||
&url_path,
|
||||
self.dir.parent().unwrap().to_path_buf(),
|
||||
)));
|
||||
} else {
|
||||
ret.push(PathEntry::Path(self.name.clone(), url_path));
|
||||
}
|
||||
if entry.starts_with("index_") && entry.ends_with(".html") {
|
||||
is_doc = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
ret
|
||||
ret.push(PathEntry(self.name.clone(), url_path));
|
||||
}
|
||||
|
||||
(ret, is_doc)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PathEntry {
|
||||
Path(String, String),
|
||||
Document(Document),
|
||||
}
|
||||
pub struct PathEntry(String, String);
|
||||
|
||||
impl PathEntry {
|
||||
pub fn url(&self) -> String {
|
||||
match self {
|
||||
PathEntry::Path(domain, path) => format!("/d/{domain}/{path}"),
|
||||
PathEntry::Document(document) => document.url(),
|
||||
}
|
||||
format!("/d/{}/{}", self.0, self.1)
|
||||
}
|
||||
|
||||
pub fn path(&self) -> String {
|
||||
match self {
|
||||
PathEntry::Path(_, path) => path.to_string(),
|
||||
PathEntry::Document(document) => document.path.clone(),
|
||||
}
|
||||
pub fn path(&self) -> &String {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +157,13 @@ impl Document {
|
|||
}
|
||||
|
||||
pub fn versions(&self) -> Vec<String> {
|
||||
read_dir(&self.doc_dir())
|
||||
let mut res: Vec<String> = read_dir(&self.doc_dir())
|
||||
.into_iter()
|
||||
.filter(|x| x.starts_with("index_") && x.ends_with(".html"))
|
||||
.collect();
|
||||
res.sort();
|
||||
res.reverse();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,12 @@ pub async fn download_favicon(domain: &str) -> Option<Vec<u8>> {
|
|||
|
||||
pub async fn download_fav_for(site: &str) {
|
||||
if let Some(fav) = download_favicon(site).await {
|
||||
std::fs::write(std::path::Path::new("./favicon").join(site), fav).unwrap();
|
||||
let fav_path = std::path::Path::new("./favicon").join(site);
|
||||
if !fav_path.exists() {
|
||||
std::fs::write(fav_path, fav).unwrap();
|
||||
log::info!("Writting favicon for {site}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn download_favicons_for_sites(sites: &[String]) {
|
||||
|
|
|
@ -7,7 +7,7 @@ use based::{
|
|||
use maud::{html, PreEscaped};
|
||||
use rocket::{get, State};
|
||||
|
||||
use crate::archive::{PathEntry, WebsiteArchive};
|
||||
use crate::archive::WebsiteArchive;
|
||||
|
||||
pub async fn render_page(content: PreEscaped<String>, ctx: RequestContext) -> StringResponse {
|
||||
based::page::render_page(
|
||||
|
@ -17,6 +17,7 @@ pub async fn render_page(content: PreEscaped<String>, ctx: RequestContext) -> St
|
|||
&Shell::new(
|
||||
html! {
|
||||
script src="https://cdn.tailwindcss.com" {};
|
||||
meta name="viewport" content="width=device-width, initial-scale=1.0" {};
|
||||
},
|
||||
html! {},
|
||||
Some("bg-zinc-950 text-white min-h-screen flex pt-8 justify-center".to_string()),
|
||||
|
@ -72,6 +73,35 @@ pub fn arrow_icon(color: &str) -> PreEscaped<String> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn slash_seperator() -> PreEscaped<String> {
|
||||
html! {
|
||||
p class="font-bold p-2 text-gray-400" { " / " };
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gen_path_link(
|
||||
path: &str,
|
||||
index: usize,
|
||||
path_seperations: &[&str],
|
||||
domain: &str,
|
||||
) -> PreEscaped<String> {
|
||||
let upto: Vec<&str> = path_seperations.iter().take(index + 1).cloned().collect();
|
||||
html! {
|
||||
a href=(format!("/d/{}/{}", domain, upto.join("/"))) { (path)}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gen_path_header(path_seperations: Vec<&str>, domain: &str) -> PreEscaped<String> {
|
||||
html! {
|
||||
@for (index, path) in path_seperations.iter().enumerate() {
|
||||
(gen_path_link(path, index, &path_seperations, domain))
|
||||
@if index < path_seperations.len()-1 {
|
||||
(slash_seperator())
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/d/<domain>/<paths..>")]
|
||||
pub async fn domain_info_route(
|
||||
ctx: RequestContext,
|
||||
|
@ -80,26 +110,64 @@ pub async fn domain_info_route(
|
|||
arc: &State<WebsiteArchive>,
|
||||
) -> StringResponse {
|
||||
let domain = arc.get_domain(domain);
|
||||
let paths = domain.paths(paths.to_str().unwrap());
|
||||
let document = domain.path(paths.to_str().unwrap());
|
||||
let versions: Vec<String> = document
|
||||
.versions()
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
x.trim_start_matches("index_")
|
||||
.trim_end_matches(".html")
|
||||
.to_string()
|
||||
})
|
||||
.collect();
|
||||
let (path_entries, is_doc) = domain.paths(paths.to_str().unwrap());
|
||||
let path_seperations: Vec<&str> = paths.to_str().unwrap().split('/').collect();
|
||||
|
||||
let content = html! {
|
||||
h2 class="text-xl font-bold mb-4" { (domain.name) };
|
||||
div class="max-w-md mx-auto p-4 bg-neutral-900 rounded-lg shadow-md" {
|
||||
ul class="space-y-2" {
|
||||
@for path in paths {
|
||||
a href=(path.url()) class="flex items-center gap-2 p-3 border bg-neutral-800 rounded hover:shadow-lg transition" {
|
||||
@if matches!(path, PathEntry::Document(_)) {
|
||||
(arrow_icon("red"))
|
||||
} @else {
|
||||
(arrow_icon("blue"))
|
||||
h2 class="text-xl font-bold mb-4 flex items-center" {
|
||||
img class="p-2" src=(format!("/favicon/{}", &domain.name)) {};
|
||||
a href=(format!("/d/{}", &domain.name)) { (domain.name) };
|
||||
(slash_seperator())
|
||||
(gen_path_header(path_seperations, &domain.name))
|
||||
};
|
||||
|
||||
@if !versions.is_empty() {
|
||||
div class="max-w-md mx-auto p-4 bg-neutral-900 rounded-lg shadow-md mb-8" {
|
||||
h3 class="font-bold mb-2" { "Saved Versions:" };
|
||||
@for (index, ver) in versions.into_iter().enumerate() {
|
||||
a href=(format!("/s/{}/{}?time={}", &domain.name, paths.to_str().unwrap(), ver)) class="text-xs text-blue-400" {
|
||||
|
||||
@if index == 0 {
|
||||
(format!("Latest ({ver})"))
|
||||
} @else {
|
||||
(ver)
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@if path_entries.is_empty() && !is_doc {
|
||||
div class="max-w-md mx-auto p-4 bg-neutral-900 rounded-lg shadow-md" {
|
||||
p class="p-4 text-xl" { "Nothing found" };
|
||||
}
|
||||
}
|
||||
|
||||
@if !path_entries.is_empty() {
|
||||
div class="max-w-md mx-auto p-4 bg-neutral-900 rounded-lg shadow-md" {
|
||||
h3 class="font-bold mb-2" { "Paths:" };
|
||||
ul class="space-y-2" {
|
||||
@for path in path_entries {
|
||||
a href=(path.url()) class="flex items-center gap-2 p-3 border bg-neutral-800 rounded hover:shadow-lg transition" {
|
||||
(arrow_icon("blue"))
|
||||
|
||||
span class="font-medium" { (path.path()) };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
render_page(content, ctx).await
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue