♻️ fragments
Some checks failed
ci/woodpecker/push/build Pipeline failed

This commit is contained in:
JMARyA 2025-03-26 21:40:43 +01:00
parent 907ed2a2ef
commit 3e9808db80
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
4 changed files with 106 additions and 6 deletions

View file

@ -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()
}
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()
}

View file

@ -62,7 +62,8 @@ async fn main() {
pages::fragment_get,
pages::mime_overview,
pages::fragments_overview,
pages::fragments_domain_overview
pages::fragments_domain_overview,
pages::fragment_overview
],
)
.manage(arc)

View file

@ -3,6 +3,7 @@ use std::{collections::HashMap, io::Read, path::PathBuf, sync::Arc};
use based::ui::components::prelude::*;
use based::ui::prelude::*;
use based::ui::primitives::div::Center;
use based::{
page,
request::{
@ -14,6 +15,7 @@ use based::{
use chrono::NaiveDate;
use itertools::Itertools;
use maud::{html, PreEscaped};
use regex::Regex;
use rocket::response::Redirect;
use rocket::{get, request::FromSegments, State};
@ -22,8 +24,8 @@ use component::*;
use serde_json::json;
use webarc::archive::{
domain_has_fragments, get_fragment, get_fragments_of_domain, get_random_fragment_id,
internalize_urls, Document, DocumentIndex,
domain_has_fragments, get_domains_of_fragment, get_fragment, get_fragments_of_domain,
get_random_fragment_id, internalize_urls, Document, DocumentIndex,
};
use webarc::get_mime_type;
use webarc::{
@ -448,6 +450,17 @@ pub async fn render_website(
.as_bytes()
.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)));
@ -458,6 +471,24 @@ pub async fn render_website(
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: &regex::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> {
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"
@ -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>")]
pub async fn fragments_domain_overview(
domain: &str,
@ -659,12 +744,15 @@ pub async fn fragments_domain_overview(
.into_iter()
.map(|(fragment, mime)| {
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(
Tooltip(
Link(&format!("/f/{fragment}"), Text(&fragment)),
Link(&format!("/fragment/{fragment}"), Text(&fragment)),
Text(&mime),
)
.white(),