This commit is contained in:
parent
907ed2a2ef
commit
3e9808db80
4 changed files with 106 additions and 6 deletions
|
@ -27,4 +27,4 @@ toml = "0.8.19"
|
||||||
url-escape = "0.1.1"
|
url-escape = "0.1.1"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
|
@ -35,3 +35,14 @@ pub async fn get_fragments_of_domain(domain: &str) -> Vec<(String, String)> {
|
||||||
|
|
||||||
res.into_iter().map(|x| (x.0, x.1)).collect()
|
res.into_iter().map(|x| (x.0, x.1)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_domains_of_fragment(fragment: &str) -> Vec<(String, String, chrono::NaiveDate)> {
|
||||||
|
let res: Vec<(String, String, chrono::NaiveDate)> =
|
||||||
|
sqlx::query_as("SELECT domain, path, version FROM document_fragments WHERE fragment = $1")
|
||||||
|
.bind(fragment)
|
||||||
|
.fetch_all(get_pg!())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
res.into_iter().map(|x| (x.0, x.1, x.2)).collect()
|
||||||
|
}
|
||||||
|
|
|
@ -62,7 +62,8 @@ async fn main() {
|
||||||
pages::fragment_get,
|
pages::fragment_get,
|
||||||
pages::mime_overview,
|
pages::mime_overview,
|
||||||
pages::fragments_overview,
|
pages::fragments_overview,
|
||||||
pages::fragments_domain_overview
|
pages::fragments_domain_overview,
|
||||||
|
pages::fragment_overview
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.manage(arc)
|
.manage(arc)
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::{collections::HashMap, io::Read, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use based::ui::components::prelude::*;
|
use based::ui::components::prelude::*;
|
||||||
use based::ui::prelude::*;
|
use based::ui::prelude::*;
|
||||||
|
use based::ui::primitives::div::Center;
|
||||||
use based::{
|
use based::{
|
||||||
page,
|
page,
|
||||||
request::{
|
request::{
|
||||||
|
@ -14,6 +15,7 @@ use based::{
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use maud::{html, PreEscaped};
|
use maud::{html, PreEscaped};
|
||||||
|
use regex::Regex;
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
use rocket::{get, request::FromSegments, State};
|
use rocket::{get, request::FromSegments, State};
|
||||||
|
|
||||||
|
@ -22,8 +24,8 @@ use component::*;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use webarc::archive::{
|
use webarc::archive::{
|
||||||
domain_has_fragments, get_fragment, get_fragments_of_domain, get_random_fragment_id,
|
domain_has_fragments, get_domains_of_fragment, get_fragment, get_fragments_of_domain,
|
||||||
internalize_urls, Document, DocumentIndex,
|
get_random_fragment_id, internalize_urls, Document, DocumentIndex,
|
||||||
};
|
};
|
||||||
use webarc::get_mime_type;
|
use webarc::get_mime_type;
|
||||||
use webarc::{
|
use webarc::{
|
||||||
|
@ -448,6 +450,17 @@ pub async fn render_website(
|
||||||
.as_bytes()
|
.as_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : Fix
|
||||||
|
// This will work if the `Content-Security-Policy` meta tag gets removed from the document
|
||||||
|
// -> Migrate to HTML parser
|
||||||
|
|
||||||
|
/*
|
||||||
|
content = replace_data_urls(
|
||||||
|
&String::from_utf8_lossy(&content),
|
||||||
|
"http://127.0.0.1:8000"
|
||||||
|
).as_bytes().to_vec();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(DataResponse::new(content, mime, Some(60 * 60 * 24)));
|
return Some(DataResponse::new(content, mime, Some(60 * 60 * 24)));
|
||||||
|
@ -458,6 +471,24 @@ pub async fn render_website(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn replace_data_urls(input: &str, root: &str) -> String {
|
||||||
|
let data_url_pattern = r#"data:([a-zA-Z0-9]+/[a-zA-Z0-9.+-]+);base64,([a-zA-Z0-9+/=]+)"#;
|
||||||
|
let re_data = Regex::new(data_url_pattern).unwrap();
|
||||||
|
|
||||||
|
re_data
|
||||||
|
.replace_all(input, |caps: ®ex::Captures| {
|
||||||
|
let encoded_data = caps.get(2).unwrap().as_str();
|
||||||
|
|
||||||
|
if let Ok(decoded) = base64::decode(encoded_data) {
|
||||||
|
let hash = webarc::sha256_hash(&decoded);
|
||||||
|
format!("{root}/f/{hash}")
|
||||||
|
} else {
|
||||||
|
caps[0].to_string()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn gen_search_element(x: &SearchResult) -> PreEscaped<String> {
|
pub fn gen_search_element(x: &SearchResult) -> PreEscaped<String> {
|
||||||
html! {
|
html! {
|
||||||
div class="text-xl font-bold mt-4 p-4 flex items-center w-full max-w-4xl max-h-40 mx-auto bg-neutral-800 shadow-md rounded-lg overflow-hidden border border-neutral-900 hover:cursor-pointer"
|
div class="text-xl font-bold mt-4 p-4 flex items-center w-full max-w-4xl max-h-40 mx-auto bg-neutral-800 shadow-md rounded-lg overflow-hidden border border-neutral-900 hover:cursor-pointer"
|
||||||
|
@ -646,6 +677,60 @@ pub async fn mime_overview(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/fragment/<fragment>")]
|
||||||
|
pub async fn fragment_overview(
|
||||||
|
fragment: &str,
|
||||||
|
ctx: RequestContext,
|
||||||
|
shell: &State<Shell>,
|
||||||
|
) -> Option<StringResponse> {
|
||||||
|
let fragment_info = get_fragment(fragment).await?;
|
||||||
|
|
||||||
|
let docs = get_domains_of_fragment(fragment).await;
|
||||||
|
|
||||||
|
let content = Margin(
|
||||||
|
Column(vec![
|
||||||
|
Center(Card(
|
||||||
|
Row(vec![
|
||||||
|
Text(fragment).render(),
|
||||||
|
Rounded(
|
||||||
|
Padding(
|
||||||
|
Background(Text(&fragment_info.1).bold().black().xs())
|
||||||
|
.color(Colors::White),
|
||||||
|
)
|
||||||
|
.all(ScreenValue::_2),
|
||||||
|
)
|
||||||
|
.render(),
|
||||||
|
Link(&format!("/f/{fragment}"), Button("Raw")).render(),
|
||||||
|
])
|
||||||
|
.gap(ScreenValue::_4)
|
||||||
|
.items_center(),
|
||||||
|
))
|
||||||
|
.render(),
|
||||||
|
Center(Card(
|
||||||
|
UnorderedList()
|
||||||
|
.push(Text("Referenced on:").bold()._2xl())
|
||||||
|
.push_for_each(&docs, |(domain, path, _): &_| {
|
||||||
|
Link(
|
||||||
|
&format!("/d/{domain}/{path}"),
|
||||||
|
Row(vec![
|
||||||
|
favicon(domain),
|
||||||
|
Text(domain).render(),
|
||||||
|
Text(path).render(),
|
||||||
|
])
|
||||||
|
.items_center(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
.render(),
|
||||||
|
])
|
||||||
|
.gap(ScreenValue::_4),
|
||||||
|
)
|
||||||
|
.top(ScreenValue::_4)
|
||||||
|
.render();
|
||||||
|
|
||||||
|
Some(page!(shell, ctx, "Fragment", content))
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/fragments/<domain>")]
|
#[get("/fragments/<domain>")]
|
||||||
pub async fn fragments_domain_overview(
|
pub async fn fragments_domain_overview(
|
||||||
domain: &str,
|
domain: &str,
|
||||||
|
@ -659,12 +744,15 @@ pub async fn fragments_domain_overview(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(fragment, mime)| {
|
.map(|(fragment, mime)| {
|
||||||
if mime.starts_with("image") {
|
if mime.starts_with("image") {
|
||||||
return Card(Image(&format!("/f/{fragment}")).height(128).width(128));
|
return Card(Link(
|
||||||
|
&format!("/fragment/{fragment}"),
|
||||||
|
Image(&format!("/f/{fragment}")).height(128).width(128),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Card(
|
Card(
|
||||||
Tooltip(
|
Tooltip(
|
||||||
Link(&format!("/f/{fragment}"), Text(&fragment)),
|
Link(&format!("/fragment/{fragment}"), Text(&fragment)),
|
||||||
Text(&mime),
|
Text(&mime),
|
||||||
)
|
)
|
||||||
.white(),
|
.white(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue