Improve FAQ & video rendering, tighten homepage and CSS
This commit is contained in:
parent
05a1f316e1
commit
c69bb0d614
48 changed files with 4689 additions and 1077 deletions
|
|
@ -11,6 +11,21 @@ use crate::state::AppState;
|
|||
const OG_PLACEHOLDER: &str =
|
||||
r#"<meta name="x-og-placeholder" content="__PERFECT_POSTCODE_OG_TAGS__"/>"#;
|
||||
|
||||
/// Escape a string for safe inclusion inside a double-quoted HTML attribute value.
|
||||
fn escape_attr(s: &str) -> String {
|
||||
let mut out = String::with_capacity(s.len());
|
||||
for c in s.chars() {
|
||||
match c {
|
||||
'&' => out.push_str("&"),
|
||||
'<' => out.push_str("<"),
|
||||
'>' => out.push_str(">"),
|
||||
'"' => out.push_str("""),
|
||||
_ => out.push(c),
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub async fn og_middleware(request: Request, next: Next) -> Response {
|
||||
let path = request.uri().path().to_string();
|
||||
// Capture the query string before passing the request through
|
||||
|
|
@ -46,32 +61,34 @@ pub async fn og_middleware(request: Request, next: Next) -> Response {
|
|||
None => return response,
|
||||
};
|
||||
|
||||
// Build OG-injected HTML (og=1 triggers heading overlay on screenshot)
|
||||
// Build OG-injected HTML (og=1 triggers heading overlay on screenshot).
|
||||
// All URL components are HTML-escaped before interpolation into attributes
|
||||
// because path/query are attacker-controlled.
|
||||
let is_invite = path.starts_with("/invite/");
|
||||
let path_e = escape_attr(&path);
|
||||
let query_e = escape_attr(&query_string);
|
||||
let public_url_e = escape_attr(&state.public_url);
|
||||
|
||||
let og_image_url = if is_invite {
|
||||
// Include path= so the screenshot service navigates to /invite/CODE
|
||||
if query_string.is_empty() {
|
||||
format!("{}/api/screenshot?og=1&path={}", state.public_url, path)
|
||||
format!("{public_url_e}/api/screenshot?og=1&path={path_e}")
|
||||
} else {
|
||||
format!(
|
||||
"{}/api/screenshot?og=1&path={}&{}",
|
||||
state.public_url, path, query_string
|
||||
)
|
||||
format!("{public_url_e}/api/screenshot?og=1&path={path_e}&{query_e}")
|
||||
}
|
||||
} else if query_string.is_empty() {
|
||||
format!("{}/api/screenshot?og=1", state.public_url)
|
||||
format!("{public_url_e}/api/screenshot?og=1")
|
||||
} else {
|
||||
format!("{}/api/screenshot?og=1&{}", state.public_url, query_string)
|
||||
format!("{public_url_e}/api/screenshot?og=1&{query_e}")
|
||||
};
|
||||
|
||||
let og_url = if query_string.is_empty() {
|
||||
format!("{}{}", state.public_url, path)
|
||||
format!("{public_url_e}{path_e}")
|
||||
} else {
|
||||
format!("{}{}?{}", state.public_url, path, query_string)
|
||||
format!("{public_url_e}{path_e}?{query_e}")
|
||||
};
|
||||
|
||||
let og_logo = format!("{}/favicon.svg", state.public_url);
|
||||
let og_logo = format!("{public_url_e}/favicon.svg");
|
||||
|
||||
let (og_title, og_description) = if is_invite {
|
||||
(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue