From 7489bd91b9c107fef55c0934f6bed74f290d17eb Mon Sep 17 00:00:00 2001 From: juanperias Date: Thu, 24 Jul 2025 14:46:31 -0400 Subject: [PATCH 1/2] refactor: clippy errors --- src/components/blog_content.rs | 10 ++++-- src/components/button_link.rs | 3 +- src/components/card_article.rs | 4 +++ .../esta_semana_en_rust/blog_content.rs | 12 ++++--- src/components/esta_semana_en_rust/header.rs | 1 + src/components/esta_semana_en_rust/layout.rs | 3 +- src/components/feature_articles.rs | 15 +++++---- src/components/header.rs | 1 + src/components/icons/comments.rs | 3 +- src/components/icons/github.rs | 1 + src/components/icons/linkedin.rs | 3 +- src/components/icons/logo_rust_page.rs | 3 +- src/components/icons/mod.rs | 2 ++ src/components/icons/next.rs | 1 + src/components/icons/twitter.rs | 1 + src/components/icons/website.rs | 1 + src/components/layout.rs | 3 +- src/components/markdown_render.rs | 2 +- src/components/mdx/center.rs | 1 + src/components/mdx/youtube.rs | 2 ++ src/components/pagination_buttons.rs | 3 ++ src/main.rs | 33 ++++++++++--------- src/meta.rs | 9 +++-- src/models/article.rs | 2 +- src/pages/article_page.rs | 1 + src/pages/esta_semana_en_rust.rs | 1 + src/pages/home.rs | 5 +-- src/render.rs | 4 ++- src/ssg.rs | 2 ++ src/utils/mod.rs | 4 ++- 30 files changed, 91 insertions(+), 45 deletions(-) diff --git a/src/components/blog_content.rs b/src/components/blog_content.rs index ecf218d..bd72cee 100644 --- a/src/components/blog_content.rs +++ b/src/components/blog_content.rs @@ -117,6 +117,8 @@ pub fn BlogContent( } #[component] +#[must_use] +#[allow(clippy::needless_pass_by_value, clippy::implicit_hasher)] pub fn ArticleHeader( #[prop()] title: String, #[prop()] github_user: Option, @@ -183,14 +185,16 @@ pub fn ArticleHeader( }) .collect::>()}
- {if !social.is_empty() { + {if social.is_empty() { + view! { + <> + } + } else { view! { <>
} - } else { - view! { <> } }} {social .iter() diff --git a/src/components/button_link.rs b/src/components/button_link.rs index 45bd0e4..ba7cb26 100644 --- a/src/components/button_link.rs +++ b/src/components/button_link.rs @@ -2,12 +2,13 @@ use leptos::{component, view, Children, IntoView}; use std::collections::HashMap; #[component] +#[must_use] pub fn ButtonLink( href: &'static str, #[prop(default = "primary")] color: &'static str, #[prop(default = "normal")] size: &'static str, #[prop(default = "drop")] shadow: &'static str, - #[prop(into, optional)] class: String, + #[prop(into, optional)] class: &'static str, children: Children, ) -> impl IntoView { let colors = HashMap::from([ diff --git a/src/components/card_article.rs b/src/components/card_article.rs index 56f8b49..fac3182 100644 --- a/src/components/card_article.rs +++ b/src/components/card_article.rs @@ -4,6 +4,7 @@ use crate::{ }; use leptos::{component, view, CollectView, IntoView}; +#[must_use] #[component] pub fn CardArticle(article: Article, is_home: bool) -> impl IntoView { let article_link = get_link(&article, is_home); @@ -67,6 +68,7 @@ fn get_description(article: &Article) -> String { } } +#[must_use] #[component] pub fn TagsList(tags: Option>) -> impl IntoView { let tags = tags.unwrap_or_default(); @@ -79,6 +81,8 @@ pub fn TagsList(tags: Option>) -> impl IntoView { } #[component] +#[allow(clippy::needless_pass_by_value)] +#[must_use] pub fn TagButton(tag: String) -> impl IntoView { let tag = tag.to_lowercase().replace(' ', "-"); diff --git a/src/components/esta_semana_en_rust/blog_content.rs b/src/components/esta_semana_en_rust/blog_content.rs index e6389aa..d618b34 100644 --- a/src/components/esta_semana_en_rust/blog_content.rs +++ b/src/components/esta_semana_en_rust/blog_content.rs @@ -42,7 +42,7 @@ pub fn BlogContent(#[prop()] article: Article) -> impl IntoView {
- {if !article.has_author() { + {if article.has_author() { view! { <>
{article.author}
@@ -51,14 +51,16 @@ pub fn BlogContent(#[prop()] article: Article) -> impl IntoView { } else { view! { <> } }} - {if !social.is_empty() { + {if social.is_empty() { + view! { + <> + } + } else { view! { <> -
+
} - } else { - view! { <> } }}
{social diff --git a/src/components/esta_semana_en_rust/header.rs b/src/components/esta_semana_en_rust/header.rs index 36e8507..a6c077b 100644 --- a/src/components/esta_semana_en_rust/header.rs +++ b/src/components/esta_semana_en_rust/header.rs @@ -2,6 +2,7 @@ use leptos::{component, create_signal, view, IntoView, SignalGet, SignalUpdate}; use crate::components::button_link::ButtonLink; +#[must_use] #[component] pub fn Header() -> impl IntoView { let (is_open, set_is_open) = create_signal(false); diff --git a/src/components/esta_semana_en_rust/layout.rs b/src/components/esta_semana_en_rust/layout.rs index 7fe7ad4..fc0fe32 100644 --- a/src/components/esta_semana_en_rust/layout.rs +++ b/src/components/esta_semana_en_rust/layout.rs @@ -10,8 +10,9 @@ fn get_year() -> i32 { chrono::Utc::now().year() } -#[component] // This is a common Layout component that will be used by all pages. +#[component] +#[must_use] pub fn Layout( #[prop(into, default=format!("Blog de Rust Lang en Español {}", get_year()))] title: String, #[prop(into, default="Somos una comunidad de Rust hispana, buscamos la promoción del lenguaje de programación Rust.".to_string())] diff --git a/src/components/feature_articles.rs b/src/components/feature_articles.rs index a6363bc..e163202 100644 --- a/src/components/feature_articles.rs +++ b/src/components/feature_articles.rs @@ -14,6 +14,11 @@ use crate::{ }; use leptos_mdx::mdx::Mdx; +/// # Panics +/// If no article is found with the tag "esta semana en rust", the call to `unwrap()` will panic. +/// If no article is found with the tag "anuncio de la comunidad", the second `unwrap()` will panic. +/// If the "video" attribute is missing in any `YouTube` component, the `unwrap()` inside the closure will panic. +/// If the value of the "video" attribute is None, the second `unwrap()` will also panic. pub async fn featured_articles() -> impl IntoView { let articles = ARTICLES.read().await.clone(); let _invalid_tags = [ @@ -24,15 +29,13 @@ pub async fn featured_articles() -> impl IntoView { let esta_semana_en_rust = articles .clone() .into_iter() - .filter(|article| filter_article_by_tag(article.clone(), "esta semana en rust".to_string())) + .filter(|article| filter_article_by_tag(article, "esta semana en rust")) .take(1) .collect::>(); let esta_semana_en_rust = esta_semana_en_rust.first().unwrap().to_owned(); let anuncio_de_la_comunidad = articles .into_iter() - .filter(|article| { - filter_article_by_tag(article.clone(), "anuncio de la comunidad".to_string()) - }) + .filter(|article| filter_article_by_tag(article, "anuncio de la comunidad")) .take(1) .collect::>(); @@ -64,9 +67,9 @@ pub async fn featured_articles() -> impl IntoView { } #[must_use] -pub fn filter_article_by_tag(article: Article, tag: String) -> bool { +pub fn filter_article_by_tag(article: &Article, tag: &str) -> bool { if let Some(tags) = &article.tags { - tags.contains(&tag) + tags.contains(&tag.to_string()) } else { false } diff --git a/src/components/header.rs b/src/components/header.rs index f80e6ae..ba849d2 100644 --- a/src/components/header.rs +++ b/src/components/header.rs @@ -4,6 +4,7 @@ use crate::components::button_link::ButtonLink; use crate::components::icons::logo_rust_page::LogoRustPageIcon; #[component] +#[must_use] pub fn Header() -> impl IntoView { let (is_open, set_is_open) = create_signal(false); diff --git a/src/components/icons/comments.rs b/src/components/icons/comments.rs index 943a708..ec43026 100644 --- a/src/components/icons/comments.rs +++ b/src/components/icons/comments.rs @@ -1,6 +1,7 @@ -use leptos::*; +use leptos::{component, view, IntoView}; #[component] +#[must_use] pub fn CommentIcon( #[prop(default = 40)] size: u32, #[prop(into, default = "fill-black".to_string())] class: String, diff --git a/src/components/icons/github.rs b/src/components/icons/github.rs index b9b84d0..dac32ca 100644 --- a/src/components/icons/github.rs +++ b/src/components/icons/github.rs @@ -1,6 +1,7 @@ use leptos::{component, view, IntoView}; #[component] +#[must_use] pub fn GithubIcon( #[prop(default = 40)] size: u32, #[prop(into, default = "fill-black".to_string())] class: String, diff --git a/src/components/icons/linkedin.rs b/src/components/icons/linkedin.rs index c852d74..62afb7b 100644 --- a/src/components/icons/linkedin.rs +++ b/src/components/icons/linkedin.rs @@ -1,6 +1,7 @@ -use leptos::*; +use leptos::{component, view, IntoView}; #[component] +#[must_use] pub fn LinkedinIcon( #[prop(default = 40)] size: u32, #[prop(into, default = "fill-black".to_string())] class: String, diff --git a/src/components/icons/logo_rust_page.rs b/src/components/icons/logo_rust_page.rs index 6b83e74..8e53089 100644 --- a/src/components/icons/logo_rust_page.rs +++ b/src/components/icons/logo_rust_page.rs @@ -1,6 +1,7 @@ -use leptos::*; +use leptos::{component, view, IntoView}; #[component] +#[must_use] pub fn LogoRustPageIcon( #[prop(default = 40)] size: u32, #[prop(into, default = "dark:fill-[#e2cea9]".to_string())] class: String, diff --git a/src/components/icons/mod.rs b/src/components/icons/mod.rs index 761c6bd..dfb9740 100644 --- a/src/components/icons/mod.rs +++ b/src/components/icons/mod.rs @@ -17,6 +17,8 @@ pub mod twitter; pub mod website; #[component] +#[must_use] +#[allow(clippy::needless_pass_by_value)] pub fn StrToIcon( #[prop(into)] v: String, #[prop(default = 40)] size: u32, diff --git a/src/components/icons/next.rs b/src/components/icons/next.rs index 05701e1..b7609c9 100644 --- a/src/components/icons/next.rs +++ b/src/components/icons/next.rs @@ -1,6 +1,7 @@ use leptos::{component, view, IntoView}; #[component] +#[must_use] pub fn NextIcon( #[prop(default = 40)] size: u32, #[prop(into, default = "fill-black".to_string())] class: String, diff --git a/src/components/icons/twitter.rs b/src/components/icons/twitter.rs index fc044bf..caacaa8 100644 --- a/src/components/icons/twitter.rs +++ b/src/components/icons/twitter.rs @@ -1,6 +1,7 @@ use leptos::{component, view, IntoView}; #[component] +#[must_use] pub fn TwitterIcon( #[prop(default = 40)] size: u32, #[prop(into, default = "fill-black".to_string())] class: String, diff --git a/src/components/icons/website.rs b/src/components/icons/website.rs index ba5c700..3386d14 100644 --- a/src/components/icons/website.rs +++ b/src/components/icons/website.rs @@ -1,6 +1,7 @@ use leptos::{component, view, IntoView}; #[component] +#[must_use] pub fn WebsiteIcon( #[prop(default = 40)] size: u32, #[prop(into, default = "fill-black".to_string())] class: String, diff --git a/src/components/layout.rs b/src/components/layout.rs index e6879f2..87ab83a 100644 --- a/src/components/layout.rs +++ b/src/components/layout.rs @@ -10,8 +10,9 @@ fn get_year() -> i32 { chrono::Utc::now().year() } -#[component] // This is a common Layout component that will be used by all pages. +#[component] +#[must_use] pub fn Layout( #[prop(into, default=format!("Blog de Rust Lang en Español {}", get_year()))] title: String, #[prop(into, default="rustlanges_preview.webp".to_string())] slug: String, diff --git a/src/components/markdown_render.rs b/src/components/markdown_render.rs index ecf3bc3..42dbeff 100644 --- a/src/components/markdown_render.rs +++ b/src/components/markdown_render.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::{component, view, IntoView}; use leptos_mdx::mdx::{Components, Mdx, MdxComponentProps}; use crate::components::mdx::{ diff --git a/src/components/mdx/center.rs b/src/components/mdx/center.rs index 1c54382..819c45e 100644 --- a/src/components/mdx/center.rs +++ b/src/components/mdx/center.rs @@ -1,6 +1,7 @@ use leptos::{component, view, Children, IntoView}; #[component] +#[must_use] pub fn Center(children: Children) -> impl IntoView { view! {
{children()}
} } diff --git a/src/components/mdx/youtube.rs b/src/components/mdx/youtube.rs index 5f9f4af..2cff0fb 100644 --- a/src/components/mdx/youtube.rs +++ b/src/components/mdx/youtube.rs @@ -1,6 +1,8 @@ use leptos::{component, view, IntoView}; #[component] +#[allow(clippy::needless_pass_by_value)] +#[must_use] pub fn Youtube(video: String) -> impl IntoView { view! {
diff --git a/src/components/pagination_buttons.rs b/src/components/pagination_buttons.rs index 71da57f..3355474 100644 --- a/src/components/pagination_buttons.rs +++ b/src/components/pagination_buttons.rs @@ -2,6 +2,7 @@ use crate::components::icons::StrToIcon; use leptos::{component, view, IntoView, Show}; #[component] +#[must_use] pub fn PaginationButtons( hide: bool, current_page: Option, @@ -34,6 +35,7 @@ pub fn PaginationButtons( } #[component] +#[must_use] pub fn PreviousPageButton(page: Option) -> impl IntoView { let page = page.unwrap_or(0); @@ -57,6 +59,7 @@ pub fn PreviousPageButton(page: Option) -> impl IntoView { } #[component] +#[must_use] pub fn NextPageButton(page: Option) -> impl IntoView { let page = page.unwrap_or(0); let link = format!("/pages/{}.html", page + 1); diff --git a/src/main.rs b/src/main.rs index b388e2d..cd12107 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,13 +10,14 @@ pub mod utils; use std::{ fs::{self, ReadDir}, path::Path, + sync::LazyLock, }; use futures::future::join_all; use futures_concurrency::prelude::*; use gray_matter::{engine::YAML, Matter}; use models::article::Article; -use once_cell::sync::Lazy; + use pages::{ article_page::ArticlePageProps, esta_semana_en_rust::{EstaSemanaEnRust, EstaSemanaEnRustProps}, @@ -28,12 +29,12 @@ use utils::generate_feed_rss; use crate::pages::{article_page::ArticlePage, home::Homepage}; -pub static ARTICLES: Lazy>> = - Lazy::new(|| RwLock::new(Vec::with_capacity(1010))); +pub static ARTICLES: LazyLock>> = + LazyLock::new(|| RwLock::new(Vec::with_capacity(1010))); #[tokio::main] async fn main() -> Result<(), Box> { - let articles = list_articles().await?; + let articles = list_articles()?; ARTICLES.write().await.extend(articles.clone()); // Set the articles in the ARTICLES static variable let out = Path::new("./out/blog"); if !out.exists() { @@ -72,7 +73,7 @@ fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> std::io::Result Ok(()) } -async fn generate_homepage<'a>(ssg: &Ssg<'a>) -> Result<(), Box> { +async fn generate_homepage(ssg: &Ssg<'_>) -> Result<(), Box> { ssg.gen("index.html".to_owned(), || { Homepage(HomepageProps { articles: None, @@ -86,9 +87,9 @@ async fn generate_homepage<'a>(ssg: &Ssg<'a>) -> Result<(), Box( +async fn generate_esta_semana_en_rust( articles: Vec
, - ssg: &Ssg<'a>, + ssg: &Ssg<'_>, ) -> Result<(), Box> { let articles = articles .into_iter() @@ -118,9 +119,9 @@ async fn generate_esta_semana_en_rust<'a>( Ok(()) } -async fn generate_post_pages<'a>( +async fn generate_post_pages( articles: Vec
, - ssg: &Ssg<'a>, + ssg: &Ssg<'_>, ) -> Result<(), Box> { tokio::fs::create_dir_all("./out/blog/articles").await?; @@ -155,9 +156,9 @@ async fn generate_post_pages<'a>( Ok(()) } -async fn generate_tag_pages<'a>( +async fn generate_tag_pages( articles: Vec
, - ssg: &Ssg<'a>, + ssg: &Ssg<'_>, ) -> Result<(), Box> { tokio::fs::create_dir_all("./out/blog/tags").await?; @@ -195,7 +196,7 @@ async fn generate_tag_pages<'a>( Ok(()) } -async fn list_articles() -> Result, Box> { +fn list_articles() -> Result, Box> { let mut articles = Vec::with_capacity(10); let article_folder = fs::read_dir("./articles")?; articles.append(&mut posts_from_folder(article_folder)?); @@ -216,7 +217,7 @@ fn posts_from_folder(paths: ReadDir) -> Result, Box::new(); let Some(parsed_entity) = matter.parse_with_struct(&algo) else { - println!("Error parsing file: {file:?}"); + println!("Error parsing file: {}", file.display()); continue; }; let content = parsed_entity.content.clone(); @@ -240,9 +241,9 @@ fn posts_from_folder(paths: ReadDir) -> Result, Box( +async fn generate_pages( mut articles: Vec
, - ssg: &Ssg<'a>, + ssg: &Ssg<'_>, ) -> Result<(), Box> { tokio::fs::create_dir_all("./out/blog/pages").await?; @@ -260,7 +261,7 @@ async fn generate_pages<'a>( let max_pages = articles.len() / 6; let mut articles = articles.chunks(6).collect::>(); articles.remove(0); - let articles = articles.to_vec(); + let articles = articles.clone(); let generate_articles = articles .iter() diff --git a/src/meta.rs b/src/meta.rs index e307899..be9400c 100644 --- a/src/meta.rs +++ b/src/meta.rs @@ -5,23 +5,26 @@ use leptos::{ IntoView, }; +#[must_use] #[component] pub fn Html( #[prop(into)] mut attrs: Attrs, - #[prop(optional,into, default= "".to_string())] class: String, + #[prop(optional, into, default = "")] class: &'static str, ) -> impl IntoView { let ctx = expect_context::(); - let mut class = Attrs::from(vec![("class", class.as_str())]); + let mut class = Attrs::from(vec![("class", class)]); ctx.body_attrs.borrow_mut().append(&mut class); ctx.html_attrs.borrow_mut().append(&mut attrs); } +#[must_use] #[component] pub fn Head(children: Children) -> impl IntoView { let ctx = expect_context::(); ctx.head_els.borrow_mut().push(children()); } +#[must_use] #[component(transparent)] pub fn Dedup(#[prop(into)] key: String, children: Children) -> impl IntoView { let ctx = expect_context::(); @@ -47,7 +50,7 @@ impl ShellCtx { } #[must_use] - pub fn render(self, inner_body: String) -> String { + pub fn render(self, inner_body: &str) -> String { let head = render_to_string(move || { view! { {self.head_els.borrow().clone().collect_view()} diff --git a/src/models/article.rs b/src/models/article.rs index 8f5bdba..98bf86b 100644 --- a/src/models/article.rs +++ b/src/models/article.rs @@ -100,7 +100,7 @@ impl From for Article { .links .github .split('/') - .last() + .next_back() .map(std::string::ToString::to_string), date: date_time, social: Some(HashMap::from([ diff --git a/src/pages/article_page.rs b/src/pages/article_page.rs index af8d73e..838dccb 100644 --- a/src/pages/article_page.rs +++ b/src/pages/article_page.rs @@ -5,6 +5,7 @@ use crate::{ models::article::Article, }; +#[must_use] #[component] pub fn ArticlePage(article: Article) -> impl IntoView { let title = article.title.clone(); diff --git a/src/pages/esta_semana_en_rust.rs b/src/pages/esta_semana_en_rust.rs index 41396a0..3ca87b7 100644 --- a/src/pages/esta_semana_en_rust.rs +++ b/src/pages/esta_semana_en_rust.rs @@ -5,6 +5,7 @@ use crate::{ models::article::Article, }; +#[must_use] #[component] pub fn EstaSemanaEnRust(article: Article) -> impl IntoView { let title = article.title.clone(); diff --git a/src/pages/home.rs b/src/pages/home.rs index 855e4e4..28e4c29 100644 --- a/src/pages/home.rs +++ b/src/pages/home.rs @@ -15,6 +15,7 @@ async fn fetch_articles() -> Vec
{ } #[component] +#[must_use] pub fn Homepage( articles: Option>, show_featured: bool, @@ -67,7 +68,7 @@ fn grid_of_articles(articles: Vec
, is_home: bool) -> impl IntoView { let articles = if is_home { articles .into_iter() - .filter(|article| filter_common_articles(article.clone(), &mut invalid_tags)) + .filter(|article| filter_common_articles(article, &mut invalid_tags)) .collect::>() .into_iter() } else { @@ -81,7 +82,7 @@ fn grid_of_articles(articles: Vec
, is_home: bool) -> impl IntoView { } } -pub fn filter_common_articles(article: Article, invalid_tags: &mut Vec) -> bool { +pub fn filter_common_articles(article: &Article, invalid_tags: &mut Vec) -> bool { if let Some(tags) = &article.tags { let invalid_tag = invalid_tags.iter().position(|tag| tags.contains(tag)); if let Some(invalid_tag) = invalid_tag { diff --git a/src/render.rs b/src/render.rs index 74fed53..cadc955 100644 --- a/src/render.rs +++ b/src/render.rs @@ -8,6 +8,8 @@ use tokio::task; use crate::meta; +/// # Panics +/// This can panic if `clean_leptos_ssr` fails during execution. pub async fn render( view: impl FnOnce() -> View + 'static, additional_context: impl FnOnce() + 'static, @@ -30,7 +32,7 @@ pub async fn render( let out = clean_leptos_ssr(stream).await.unwrap(); runtime.dispose(); - shell_ctx2.render(out) + shell_ctx2.render(&out) }) .await } diff --git a/src/ssg.rs b/src/ssg.rs index 1d236b2..b261afe 100644 --- a/src/ssg.rs +++ b/src/ssg.rs @@ -15,6 +15,8 @@ impl<'a> Ssg<'a> { Self { out_dir } } + /// # Errors + /// This can return an error if `fs::write` fails. pub async fn gen( &'a self, path: String, diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 0a832fd..37f3773 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -4,6 +4,8 @@ use rss::{validation::Validate, Category, ChannelBuilder, Item}; use crate::models::article::Article; +/// # Panics +/// This can panic if `validate` fails or if `fs::write` fails. pub fn generate_feed_rss( articles: &[Article], out_file: &str, @@ -28,7 +30,7 @@ pub fn generate_feed_rss( .get(..4) .unwrap_or_default() .iter() - .map(|a| a.into()) + .map(Into::into) .collect::>(); let channel = ChannelBuilder::default() From c14494b00453128b8d01abf13e3306bfedff7daa Mon Sep 17 00:00:00 2001 From: juanperias Date: Thu, 24 Jul 2025 14:50:33 -0400 Subject: [PATCH 2/2] chore: leptosfmt --- src/components/blog_content.rs | 4 +--- src/components/esta_semana_en_rust/blog_content.rs | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/blog_content.rs b/src/components/blog_content.rs index bd72cee..293ffc5 100644 --- a/src/components/blog_content.rs +++ b/src/components/blog_content.rs @@ -186,9 +186,7 @@ pub fn ArticleHeader( .collect::>()}
{if social.is_empty() { - view! { - <> - } + view! { <> } } else { view! { <> diff --git a/src/components/esta_semana_en_rust/blog_content.rs b/src/components/esta_semana_en_rust/blog_content.rs index d618b34..050d610 100644 --- a/src/components/esta_semana_en_rust/blog_content.rs +++ b/src/components/esta_semana_en_rust/blog_content.rs @@ -52,13 +52,11 @@ pub fn BlogContent(#[prop()] article: Article) -> impl IntoView { view! { <> } }} {if social.is_empty() { - view! { - <> - } + view! { <> } } else { view! { <> -
+
} }}