Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c22b52fda | ||
|
|
01504fb120 |
Generated
+1
-1
@@ -2948,7 +2948,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portal"
|
name = "portal"
|
||||||
version = "0.3.30"
|
version = "0.3.31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "portal"
|
name = "portal"
|
||||||
version = "0.3.31"
|
version = "0.3.32"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|||||||
+10
-1
@@ -1,5 +1,5 @@
|
|||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
use leptos_meta::{provide_meta_context, HashedStylesheet, Html, MetaTags, Stylesheet, Title};
|
use leptos_meta::{provide_meta_context, HashedStylesheet, Html, Link, MetaTags, Stylesheet, Title};
|
||||||
use leptos_router::{
|
use leptos_router::{
|
||||||
components::{Route, Router, Routes},
|
components::{Route, Router, Routes},
|
||||||
hooks::{use_location, use_navigate, use_query_map},
|
hooks::{use_location, use_navigate, use_query_map},
|
||||||
@@ -89,10 +89,19 @@ pub fn App() -> impl IntoView {
|
|||||||
.and_then(|s| s.stylesheet)
|
.and_then(|s| s.stylesheet)
|
||||||
.map(|p| format!("/site/{p}"))
|
.map(|p| format!("/site/{p}"))
|
||||||
});
|
});
|
||||||
|
// A content-shipped favicon overrides the built-in one; injected
|
||||||
|
// into the head after the static defaults, so it wins.
|
||||||
|
let favicon = Memo::new(move |_| {
|
||||||
|
site.get()
|
||||||
|
.and_then(|r| r.ok())
|
||||||
|
.and_then(|s| s.favicon)
|
||||||
|
.map(|p| format!("/site/{p}"))
|
||||||
|
});
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Html attr:lang=move || lang.get()/>
|
<Html attr:lang=move || lang.get()/>
|
||||||
{move || custom_css.get().map(|href| view! { <Stylesheet id="site-custom" href=href/> })}
|
{move || custom_css.get().map(|href| view! { <Stylesheet id="site-custom" href=href/> })}
|
||||||
|
{move || favicon.get().map(|href| view! { <Link rel="icon" href=href/> })}
|
||||||
<Suspense fallback=|| ()>
|
<Suspense fallback=|| ()>
|
||||||
{move || {
|
{move || {
|
||||||
site.get()
|
site.get()
|
||||||
|
|||||||
@@ -611,6 +611,10 @@ pub struct SiteConfig {
|
|||||||
/// same-origin at `/site/<path>`; plain path only.
|
/// same-origin at `/site/<path>`; plain path only.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub stylesheet: Option<String>,
|
pub stylesheet: Option<String>,
|
||||||
|
/// A content-repo-relative favicon (svg/png/ico), served at
|
||||||
|
/// `/site/<path>` and used in place of the built-in one.
|
||||||
|
#[serde(default)]
|
||||||
|
pub favicon: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub hero: HeroConfig,
|
pub hero: HeroConfig,
|
||||||
}
|
}
|
||||||
@@ -673,6 +677,14 @@ impl SiteConfig {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(icon) = &self.favicon {
|
||||||
|
let ok = [".svg", ".png", ".ico"].iter().any(|e| icon.ends_with(e));
|
||||||
|
if !is_safe_site_path(icon) || !ok {
|
||||||
|
anyhow::bail!(
|
||||||
|
"site.yaml: favicon {icon:?} must be a plain repo-relative .svg/.png/.ico path"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1537,6 +1549,7 @@ pub async fn site_asset_handler(
|
|||||||
Some("png") => "image/png",
|
Some("png") => "image/png",
|
||||||
Some("webp") => "image/webp",
|
Some("webp") => "image/webp",
|
||||||
Some("avif") => "image/avif",
|
Some("avif") => "image/avif",
|
||||||
|
Some("ico") => "image/x-icon",
|
||||||
Some("woff2") => "font/woff2",
|
Some("woff2") => "font/woff2",
|
||||||
_ => "application/octet-stream",
|
_ => "application/octet-stream",
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user