2023-04-07 17:16:43 -05:00
//! # Rust Letter Frontend
//!
//! Rendering functions for the site using [Dioxus](https://dioxuslabs.com/).
#![ allow(non_snake_case) ]
/// A module that handles the functions needed
/// to render the site.
pub mod void_app {
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
pub use dioxus ::prelude ::* ;
2023-04-08 20:47:51 -05:00
use markdown ::{ self , Options } ;
2023-04-09 11:27:28 -05:00
use rust_embed ::RustEmbed ;
2023-04-11 19:42:46 -05:00
use std ::collections ::VecDeque ;
2023-04-12 17:25:14 -05:00
use dioxus_router ::{ Route , Router , Redirect } ;
2023-04-07 17:16:43 -05:00
2023-04-08 20:47:51 -05:00
#[ cfg(any(target_family = " wasm " )) ]
2023-04-09 11:27:28 -05:00
use dioxus_helmet ::Helmet ;
#[ cfg(any(target_family = " wasm " )) ]
2023-04-12 17:25:14 -05:00
use dioxus_router ::{ Link } ;
#[ cfg(any(target_family = " wasm " )) ]
use dioxus_use_storage ::use_local_storage ;
#[ cfg(any(target_family = " wasm " )) ]
use serde ::Deserialize ;
#[ cfg(target_family = " wasm " ) ]
#[ derive(Deserialize) ]
struct CurrentPoem {
current : String ,
}
2023-04-07 17:16:43 -05:00
2023-04-08 12:40:57 -05:00
#[ derive(PartialEq, Props) ]
2023-04-08 20:47:51 -05:00
pub struct PoemRequest {
2023-04-09 12:34:40 -05:00
pub slug : String ,
2023-04-10 18:19:02 -05:00
pub dark_mode : Option < bool > ,
}
#[ derive(PartialEq, Props) ]
2023-04-11 19:42:46 -05:00
pub struct DarkModeProps {
2023-04-10 18:19:02 -05:00
pub dark_mode : bool ,
2023-04-11 19:42:46 -05:00
pub slug : Option < String > ,
}
#[ derive(PartialEq, Props) ]
struct ButtonProps {
title : String ,
slug : String ,
2023-04-08 12:40:57 -05:00
}
#[ derive(PartialEq, Props) ]
2023-04-08 20:47:51 -05:00
struct PoemData {
title : Option < String > ,
content : Option < String > ,
creation_date : Option < String > ,
slug : Option < String > ,
2023-04-10 18:19:02 -05:00
dark_mode : Option < bool > ,
2023-04-07 17:16:43 -05:00
}
2023-04-09 11:27:28 -05:00
2023-04-11 19:42:46 -05:00
#[ derive(Props) ]
struct PoemChildren < ' a > {
children : Element < ' a > ,
}
2023-04-07 17:16:43 -05:00
#[ derive(RustEmbed) ]
#[ folder = " data/poems " ]
pub struct Poems ;
2023-04-08 20:47:51 -05:00
pub fn DioxusApp ( cx : Scope ) -> Element {
2023-04-12 17:25:14 -05:00
// use dioxus_router::Redirect;
2023-04-09 11:27:28 -05:00
2023-04-08 20:47:51 -05:00
cx . render ( rsx! {
Router {
2023-04-12 17:25:14 -05:00
Route { to : " / " , HomePage { dark_mode : true , } }
Route { to : " /poems/ " , PoemListPage { slug : " " . to_string ( ) , dark_mode : true , } }
Route { to : " /poems/:slug " , PoemPage { slug : " " . to_string ( ) , dark_mode : true , } }
2023-04-09 11:27:28 -05:00
Route { to : " " , PageNotFound { } }
2023-04-08 20:47:51 -05:00
}
} )
}
2023-04-09 11:27:28 -05:00
#[ cfg(target_family = " wasm " ) ]
2023-04-12 17:25:14 -05:00
fn RoutePreviousPage ( cx : Scope < PoemRequest > ) -> Element {
let current = String ::from ( dioxus_router ::use_route ( cx )
. segment ( " slug " )
. expect ( " Slug to know which poem we are at. " ) ) ;
log ::info! ( " {} " , current . clone ( ) ) ;
let previous = current . clone ( ) ;
cx . render ( rsx! {
Redirect { to : " {previous} " }
} )
}
#[ cfg(target_family = " wasm " ) ]
fn RouteNextPage ( cx : Scope < PoemRequest > ) -> Element {
let current = String ::from ( dioxus_router ::use_route ( cx )
. segment ( " slug " )
. expect ( " Slug to know which poem we are at. " ) ) ;
let next = current . clone ( ) ;
cx . render ( rsx! {
Redirect { to : " {next} " }
} )
}
2023-04-09 11:27:28 -05:00
fn PageNotFound ( cx : Scope ) -> Element {
cx . render ( rsx! {
p { " That page doesn't exist, sorry! " }
Redirect { to : " / " }
} )
}
2023-04-11 19:42:46 -05:00
fn MutantStandardFooter ( cx : Scope ) -> Element {
cx . render ( rsx! {
2023-04-12 17:25:14 -05:00
div { class : " flex p-4 mx-auto max-w-full justify-center text-md text-center ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
2023-04-11 19:42:46 -05:00
" This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License "
}
} )
}
fn BackToHomePage ( cx : Scope ) -> Element {
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " windows " , target_family = " unix " )) ]
return cx . render ( rsx! {
2023-04-11 19:42:46 -05:00
a { class : " flex justify-center p-4 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
href : " / " ,
p {
" Back to the homepage "
}
}
2023-04-12 17:25:14 -05:00
} ) ;
#[ cfg(target_family = " wasm " ) ]
return cx . render ( rsx! {
Link { class : " flex justify-center p-4 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
to : " / " ,
2023-04-11 19:42:46 -05:00
p {
" Back to the homepage "
}
}
2023-04-12 17:25:14 -05:00
} ) ;
2023-04-11 19:42:46 -05:00
}
fn NavigationButton ( cx : Scope < ButtonProps > ) -> Element {
let title = cx . props . title . clone ( ) ;
let title_ref = title . as_str ( ) ;
let slug = cx . props . slug . clone ( ) ;
let slug_ref = slug . as_str ( ) ;
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " windows " , target_family = " unix " )) ]
return cx . render ( rsx! {
2023-04-11 22:37:23 -05:00
a { class : " flex mx-auto max-w-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
2023-04-11 19:42:46 -05:00
href : " {slug_ref} " ,
" {title_ref} "
}
2023-04-12 17:25:14 -05:00
} ) ;
#[ cfg(target_family = " wasm " ) ]
return cx . render ( rsx! {
Link { class : " flex mx-auto max-w-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
to : " {slug_ref} " ,
div {
dangerous_inner_html : " {title_ref} " ,
}
2023-04-11 19:42:46 -05:00
}
2023-04-12 17:25:14 -05:00
} ) ;
2023-04-11 19:42:46 -05:00
}
fn DarkModeButton ( cx : Scope < DarkModeProps > ) -> Element {
let slug = cx
. props
. slug
. clone ( )
. expect ( " Slug found to know where to redirect after dark mode setting. " ) ;
let slug_ref = slug . as_str ( ) ;
let dark_mode = cx . props . dark_mode ;
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " windows " , target_family = " unix " )) ]
return cx . render ( rsx! {
2023-04-12 00:42:59 -05:00
a { href : " /?dark_mode&callback={slug_ref} " ,
2023-04-11 19:42:46 -05:00
match dark_mode {
true = > {
rsx! {
img { src : " /images/white_square_button.png " ,
alt : " A white square button that can toggle dark mode. " ,
}
}
} ,
false = > {
rsx! {
img { src : " /images/black_square_button.png " ,
alt : " A black square button that can toggle dark mode. " ,
}
}
} ,
}
}
2023-04-12 17:25:14 -05:00
} ) ;
#[ cfg(target_family = " wasm " ) ]
return cx . render ( rsx! {
2023-04-11 19:42:46 -05:00
Link { to : " {slug_ref}/toggle-dark-mode " ,
match dark_mode {
true = > {
rsx! {
img { src : " /images/white_square_button.png " ,
alt : " A white square button that can toggle dark mode. " ,
}
}
} ,
false = > {
rsx! {
img { src : " /images/black_square_button.png " ,
alt : " A black square button that can toggle dark mode. " ,
}
}
} ,
}
}
2023-04-12 17:25:14 -05:00
} ) ;
2023-04-11 19:42:46 -05:00
}
fn PoemButton ( cx : Scope < ButtonProps > ) -> Element {
let title = cx . props . title . clone ( ) ;
let title_ref = title . as_str ( ) ;
let slug = cx . props . slug . clone ( ) ;
let slug_ref = slug . as_str ( ) ;
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " unix " , target_family = " windows " )) ]
return cx . render ( rsx! {
2023-04-11 19:42:46 -05:00
a { href : " /poems/{slug_ref} " ,
2023-04-11 22:37:23 -05:00
li { class : " p-4 ml-2 mr-2 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
2023-04-11 19:42:46 -05:00
" {title_ref} "
}
}
2023-04-12 17:25:14 -05:00
} ) ;
#[ cfg(target_family = " wasm " ) ]
return cx . render ( rsx! {
2023-04-11 19:42:46 -05:00
Link { to : " /poems/{slug_ref} " ,
2023-04-11 22:37:23 -05:00
li { class : " p-4 ml-2 mr-2 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
2023-04-12 17:25:14 -05:00
dangerous_inner_html : " {title_ref} " ,
2023-04-11 19:42:46 -05:00
}
}
2023-04-12 17:25:14 -05:00
} ) ;
2023-04-11 19:42:46 -05:00
}
2023-04-07 17:16:43 -05:00
/// Renders the app and returns the rendered Element.
2023-04-11 19:42:46 -05:00
pub fn HomePage ( cx : Scope < DarkModeProps > ) -> Element {
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " unix " , target_family = " windows " )) ]
2023-04-11 19:42:46 -05:00
let slug = cx . props . slug . clone ( ) . expect ( " Slug for dark mode redirect. " ) ;
2023-04-12 17:25:14 -05:00
#[ cfg(target_family = " wasm " ) ]
let slug = " " . to_string ( ) ;
let oldest_uri = format! ( " /poems/ {} " , get_oldest_entry ( ) ) ;
let latest_uri = format! ( " /poems/ {} " , get_latest_entry ( ) ) ;
let title = " A Letter to the Void " . to_string ( ) ;
2023-04-10 18:19:02 -05:00
let dark_mode = cx . props . dark_mode . clone ( ) ;
2023-04-08 20:47:51 -05:00
cx . render ( rsx! {
2023-04-07 17:16:43 -05:00
div { class : " min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey " ,
div { class : " container space-y-4 mx-auto p-4 " ,
2023-04-11 19:42:46 -05:00
div { class : " p-4 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
2023-04-10 20:37:40 -05:00
p { class : " flex flex-row mx-auto max-w-full justify-center text-xl text-center " ,
2023-04-12 17:25:14 -05:00
" {title} "
2023-04-11 19:42:46 -05:00
DarkModeButton { slug : slug , dark_mode : dark_mode }
2023-04-08 20:47:51 -05:00
}
}
2023-04-11 22:37:23 -05:00
div { class : " flex p-4 ml-2 mr-2 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
2023-04-10 20:37:40 -05:00
p { class : " text-lg text-center " ,
" Welcome, and I hope you enjoy your stay! "
2023-04-11 22:37:23 -05:00
br { }
2023-04-10 20:37:40 -05:00
" \" A Letter to the Void \" is a passion project of mine in which I wrote poems about my past life experiences, present, and hopes for the future throughout my transition. "
2023-04-11 22:37:23 -05:00
br { }
2023-04-10 20:37:40 -05:00
" The topics range from my feelings through transitioning (of course), past abuse, mental health exploration, and an overall journey to grow and become a better creature. "
br { }
" I hope you enjoy the time you spend here, and sincerely, thank you. "
br { }
br { }
" 🖤 Alice Icehart Werefox "
}
}
2023-04-12 17:25:14 -05:00
NavigationButton { title : " See Latest Entry " . to_string ( ) , slug : latest_uri }
NavigationButton { title : " See Oldest Entry " . to_string ( ) , slug : oldest_uri }
2023-04-11 19:42:46 -05:00
NavigationButton { title : " See All Entries " . to_string ( ) , slug : " /poems " . to_string ( ) }
MutantStandardFooter { }
2023-04-07 17:16:43 -05:00
}
}
2023-04-08 20:47:51 -05:00
} )
2023-04-07 17:16:43 -05:00
}
2023-04-09 11:27:28 -05:00
fn get_poem_list ( ) -> Vec < ( String , String ) > {
let mut poem_list = Vec ::new ( ) ;
for p in Poems ::iter ( ) {
let filename = p . to_string ( ) ;
let poem_content = Poems ::get ( & filename ) . expect ( " Found poem {filename:?} " ) ;
let mut poem_to_str = std ::str ::from_utf8 ( poem_content . data . as_ref ( ) )
. expect ( " Title is valid UT8. " )
. lines ( ) ;
let title_markdown = poem_to_str . next ( ) . expect ( " No title specified. " ) ;
let title = markdown ::to_html_with_options ( title_markdown , & Options ::gfm ( ) ) . unwrap ( ) ;
let slug = String ::from ( filename . trim_end_matches ( " .md " ) ) ;
poem_list . push ( ( title . clone ( ) , slug . clone ( ) ) ) ;
}
log ::trace! ( " {poem_list:?} " ) ;
poem_list
}
2023-04-10 20:37:40 -05:00
pub fn get_oldest_entry ( ) -> String {
let mut poem_list = VecDeque ::from ( get_poem_list ( ) ) ;
2023-04-11 19:42:46 -05:00
poem_list
. pop_front ( )
. expect ( " There is an entry in this list of poems. " )
. 1
2023-04-10 20:37:40 -05:00
}
pub fn get_latest_entry ( ) -> String {
let mut poem_list = get_poem_list ( ) ;
2023-04-11 19:42:46 -05:00
poem_list
. pop ( )
. expect ( " There is an entry in this list of poems. " )
. 1
}
pub fn get_previous_entry ( slug : String ) -> Option < String > {
let poem_list = get_poem_list ( ) ;
poem_list . iter ( ) . enumerate ( ) . find_map ( | ( index , p ) | {
if p . 1 = = slug {
if index ! = 0 {
Some ( poem_list [ index - 1 ] . 1. clone ( ) )
} else {
None
}
} else {
None
}
} )
2023-04-10 20:37:40 -05:00
}
2023-04-11 19:42:46 -05:00
pub fn get_next_entry ( slug : String ) -> Option < String > {
let poem_list = get_poem_list ( ) ;
poem_list . iter ( ) . enumerate ( ) . find_map ( | ( index , p ) | {
if p . 1 = = slug {
if index ! = poem_list . len ( ) - 1 {
Some ( poem_list [ index + 1 ] . 1. clone ( ) )
} else {
None
}
} else {
None
}
} )
}
2023-04-10 20:37:40 -05:00
/// Renders the app and returns the rendered Element.
2023-04-11 19:42:46 -05:00
pub fn PoemListPage ( cx : Scope < DarkModeProps > ) -> Element {
let slug = cx . props . slug . clone ( ) . expect ( " Slug for dark mode redirect. " ) ;
2023-04-10 20:37:40 -05:00
let dark_mode = cx . props . dark_mode . clone ( ) ;
cx . render ( rsx! {
div { class : " min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey " ,
div { class : " container space-y-4 mx-auto p-4 " ,
2023-04-11 19:42:46 -05:00
div { class : " p-4 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
2023-04-10 20:37:40 -05:00
p { class : " flex flex-row mx-auto max-w-full justify-center text-lg text-center " ,
" A Letter to the Void "
2023-04-11 19:42:46 -05:00
DarkModeButton { slug : slug , dark_mode : dark_mode }
2023-04-10 20:37:40 -05:00
}
}
2023-04-11 19:42:46 -05:00
BackToHomePage { }
2023-04-10 20:37:40 -05:00
PoemList { }
2023-04-11 19:42:46 -05:00
BackToHomePage { }
MutantStandardFooter { }
2023-04-10 20:37:40 -05:00
}
}
} )
}
2023-04-09 11:27:28 -05:00
fn PoemList ( cx : Scope ) -> Element {
let poem_list = get_poem_list ( ) ;
cx . render ( rsx! {
2023-04-11 19:42:46 -05:00
ul { class : " flex flex-col space-y-4 " ,
2023-04-09 11:27:28 -05:00
poem_list . into_iter ( ) . map ( | p | {
rsx! {
2023-04-11 19:42:46 -05:00
PoemButton { title : p . 0 , slug : p . 1 }
2023-04-09 11:27:28 -05:00
}
} )
}
} )
}
2023-04-08 20:47:51 -05:00
pub fn PoemPage ( cx : Scope < PoemRequest > ) -> Element {
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " unix " , target_family = " windows " )) ]
2023-04-11 19:42:46 -05:00
let slug = cx . props . slug . clone ( ) ;
2023-04-12 17:25:14 -05:00
#[ cfg(target_family = " wasm " ) ]
let slug = String ::from (
dioxus_router ::use_route ( cx )
. segment ( " slug " )
. expect ( " No slug specified. " ) ,
) ;
let mut oldest_uri = get_oldest_entry ( ) ;
if oldest_uri = = slug . to_string ( ) {
oldest_uri = format! ( " /poems/ {slug} # " ) ;
2023-04-11 19:42:46 -05:00
}
2023-04-12 17:25:14 -05:00
let previous_uri = match get_previous_entry ( slug . clone ( ) ) {
Some ( p ) = > format! ( " /poems/ {p} " ) ,
None = > format! ( " /poems/ {slug} # " ) ,
} ;
let next_uri = match get_next_entry ( slug . clone ( ) ) {
Some ( p ) = > format! ( " /poems/ {p} " ) ,
None = > format! ( " /poems/ {slug} # " ) ,
} ;
let mut latest_uri = get_latest_entry ( ) ;
if latest_uri = = slug . to_string ( ) {
latest_uri = format! ( " {slug} # " ) ;
2023-04-11 19:42:46 -05:00
}
let dark_mode = cx
. props
. dark_mode
. clone ( )
. expect ( " Dark mode prop not passed. " ) ;
2023-04-08 20:47:51 -05:00
cx . render ( rsx! {
div { class : " min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey " ,
2023-04-09 12:34:40 -05:00
div { class : " container space-y-4 mx-auto p-4 " ,
2023-04-11 19:42:46 -05:00
BackToHomePage { }
GetPoem { slug : slug , dark_mode : dark_mode }
div { class : " grid md:grid-cols-4 md:grid-rows-1 grid-cols-1 grid-rows-4 gap-y-4 " ,
NavigationButton { title : " Oldest " . to_string ( ) , slug : oldest_uri }
NavigationButton { title : " Previous " . to_string ( ) , slug : previous_uri }
NavigationButton { title : " Next " . to_string ( ) , slug : next_uri }
NavigationButton { title : " Latest " . to_string ( ) , slug : latest_uri }
2023-04-10 20:37:40 -05:00
}
2023-04-11 19:42:46 -05:00
BackToHomePage { }
MutantStandardFooter { }
2023-04-09 12:34:40 -05:00
}
2023-04-08 20:47:51 -05:00
}
} )
}
fn GetPoem ( cx : Scope < PoemData > ) -> Element {
2023-04-11 19:42:46 -05:00
// It would be good to implement some kind of "get_poem_data" or "into" functionality for the struct, so I don't have to write all this here.
let dark_mode = cx
. props
. dark_mode
. clone ( )
. expect ( " Dark mode prop not passed. " ) ;
2023-04-10 18:19:02 -05:00
let slug = String ::from ( cx . props . slug . clone ( ) . expect ( " No slug specified. " ) ) ;
2023-04-11 19:42:46 -05:00
let filename = String ::from ( String ::from ( slug . clone ( ) ) + " .md " ) ;
2023-04-09 11:27:28 -05:00
let creation_date =
String ::from ( String ::from ( " <br>Written on: " ) + filename . split ( " _ " ) . next ( ) . unwrap ( ) ) ;
2023-04-08 20:47:51 -05:00
let poem_content = Poems ::get ( & filename ) . expect ( " Found poem {filename:?} " ) ;
2023-04-09 11:27:28 -05:00
let mut poem_to_str = std ::str ::from_utf8 ( poem_content . data . as_ref ( ) )
. expect ( " Title is valid UT8. " )
. lines ( ) ;
2023-04-08 20:47:51 -05:00
let poem_title = poem_to_str . next ( ) . unwrap ( ) ;
let poem_content = poem_to_str . into_iter ( ) . collect ::< Vec < & str > > ( ) . join ( " \n " ) ;
2023-04-09 11:27:28 -05:00
let poem_title_to_html_string =
markdown ::to_html_with_options ( poem_title , & Options ::gfm ( ) ) . unwrap ( ) ;
let poem_content_to_html_string =
markdown ::to_html_with_options ( poem_content . as_str ( ) , & Options ::gfm ( ) ) . unwrap ( ) ;
2023-04-11 19:42:46 -05:00
cx . render ( rsx! {
MakePoem {
RenderPoemTitle { title : poem_title_to_html_string , slug : slug , dark_mode : dark_mode }
RenderPoemElement { content : poem_content_to_html_string , creation_date : creation_date }
} } )
2023-04-08 20:47:51 -05:00
}
2023-04-11 19:42:46 -05:00
// #[cfg(any(target_family = "unix", target_family = "windows"))]
2023-04-08 20:47:51 -05:00
fn RenderPoemTitle ( cx : Scope < PoemData > ) -> Element {
2023-04-10 18:19:02 -05:00
let slug = cx . props . slug . clone ( ) . expect ( " Slug prop was not passed. " ) ;
2023-04-12 00:42:59 -05:00
let callback = format! ( " /poems/ {slug} " ) ;
2023-04-11 19:42:46 -05:00
let dark_mode = cx
. props
. dark_mode
. clone ( )
. expect ( " Dark mode prop not passed. " ) ;
2023-04-08 20:47:51 -05:00
let title = cx . props . title . clone ( ) . expect ( " No title specified. " ) ;
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " unix " , target_family = " windows " )) ]
return cx . render ( rsx! {
2023-04-11 22:37:23 -05:00
span { class : " p-4 ml-2 mr-2 flex text-xl text-center ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
2023-04-10 20:37:40 -05:00
span { class : " flex flex-row align-middle mx-auto max-w-full justify-center " ,
" {title} "
2023-04-12 00:42:59 -05:00
DarkModeButton { slug : callback , dark_mode : dark_mode }
2023-04-10 20:37:40 -05:00
}
2023-04-08 12:40:57 -05:00
}
2023-04-12 17:25:14 -05:00
} ) ;
#[ cfg(target_family = " wasm " ) ]
return cx . render ( rsx! {
span { class : " p-4 ml-2 mr-2 flex text-xl text-center ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
span { class : " flex flex-row align-middle mx-auto max-w-full justify-center " ,
div { dangerous_inner_html : " {title} " , }
DarkModeButton { slug : callback , dark_mode : dark_mode }
}
}
} ) ;
2023-04-08 12:40:57 -05:00
}
2023-04-08 20:47:51 -05:00
fn RenderPoemElement ( cx : Scope < PoemData > ) -> Element {
let content = cx . props . content . clone ( ) . expect ( " No content specified. " ) ;
2023-04-09 11:27:28 -05:00
let creation_date = cx
. props
. creation_date
. clone ( )
. expect ( " No creation date specified. " ) ;
2023-04-12 17:25:14 -05:00
#[ cfg(any(target_family = " unix " , target_family = " windows " )) ]
return cx . render ( rsx! {
2023-04-11 22:37:23 -05:00
div { class : " flex p-2 mx-auto max-w-full justify-center " ,
2023-04-11 19:42:46 -05:00
details { class : " group p-4 max-w-fit space-y-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-4 ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
2023-04-11 22:37:23 -05:00
summary { class : " group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
2023-04-11 19:42:46 -05:00
}
2023-04-11 22:37:23 -05:00
div { class : " font-nerd flex flex-col space-y-4 py-4 " , " {content}{creation_date} "
2023-04-11 19:42:46 -05:00
}
}
2023-04-10 18:19:02 -05:00
}
2023-04-12 17:25:14 -05:00
} ) ;
#[ cfg(target_family = " wasm " ) ]
return cx . render ( rsx! {
div { class : " flex p-2 mx-auto max-w-full justify-center " ,
details { class : " group p-4 max-w-fit space-y-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-4 ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light " ,
summary { class : " group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition " ,
}
div { class : " font-nerd flex flex-col space-y-4 py-4 " ,
dangerous_inner_html : " {content}{creation_date} " ,
}
}
2023-04-08 20:47:51 -05:00
}
2023-04-12 17:25:14 -05:00
} ) ;
2023-04-07 17:16:43 -05:00
}
2023-04-11 19:42:46 -05:00
fn MakePoem < ' a > ( cx : Scope < ' a , PoemChildren < ' a > > ) -> Element {
cx . render ( rsx! {
2023-04-07 17:16:43 -05:00
div { class : " flex-col space-y-4 " ,
2023-04-11 19:42:46 -05:00
& cx . props . children
2023-04-07 17:16:43 -05:00
}
2023-04-08 20:47:51 -05:00
} )
2023-04-07 17:16:43 -05:00
}
}