1
1
use perseus:: prelude:: * ;
2
2
use serde:: { Deserialize , Serialize } ;
3
+ use std:: io;
3
4
use std:: time:: Duration ;
4
5
use sycamore:: prelude:: * ;
5
6
6
7
#[ perseus:: main( perseus_warp:: dflt_server) ]
7
8
pub fn main < G : Html > ( ) -> PerseusApp < G > {
8
9
PerseusApp :: new ( ) . template (
9
10
Template :: build ( "post" )
10
- . template_with_state ( post_page)
11
+ . view_with_state ( post_page)
11
12
. build_paths_fn ( get_build_paths)
12
13
. build_state_fn ( get_build_state)
13
14
// Reload every blog post every day, in case it's changed
14
15
. revalidate_after ( Duration :: new ( 60 * 60 * 24 , 0 ) )
15
16
// If the user requests a page we haven't created yet, still
16
17
// pass it to `get_build_state()` and cache the output for
17
18
// future users (lazy page building)
18
- . incremental_generation ( ) ,
19
+ . incremental_generation ( )
20
+ . build ( ) ,
19
21
)
20
22
}
21
23
24
+ #[ auto_scope]
22
25
// EXCERPT_START
23
- #[ perseus:: template]
24
- fn post_page < ' a , G : Html > ( cx : Scope < ' a > , props : PostRx < ' a > ) -> View < G > {
26
+ fn post_page < G : Html > ( cx : Scope , state : & PostRx ) -> View < G > {
25
27
view ! { cx,
26
- h1 { ( props . title. get( ) ) }
27
- p { ( props . author. get( ) ) }
28
+ h1 { ( state . title. get( ) ) }
29
+ p { ( state . author. get( ) ) }
28
30
div(
29
- dangerously_set_inner_html = & props . content. get( )
31
+ dangerously_set_inner_html = & state . content. get( )
30
32
)
31
33
}
32
34
}
33
35
// EXCERPT_END
34
36
35
- #[ derive( Serialize , Deserialize , ReactiveState ) ]
37
+ #[ derive( Serialize , Deserialize , Clone , ReactiveState ) ]
36
38
#[ rx( alias = "PostRx" ) ]
37
39
struct Post {
38
40
title : String ,
@@ -45,24 +47,29 @@ struct Post {
45
47
#[ engine_only_fn]
46
48
async fn get_build_state (
47
49
StateGeneratorInfo { path, .. } : StateGeneratorInfo < ( ) > ,
48
- ) -> RenderFnResultWithCause < Post > {
50
+ ) -> Result < Post , BlamedError < MyError > > {
49
51
let raw_post = match get_post_for_path ( path) {
50
52
Ok ( post) => post,
51
53
// If the user sends us some bogus path with incremental generation,
52
54
// return a 404 appropriately
53
- Err ( err) => blame_err ! ( client, 404 , err) ,
55
+ Err ( err) => {
56
+ return Err ( BlamedError {
57
+ blame : ErrorBlame :: Client ( Some ( 404 ) ) ,
58
+ error : MyError ,
59
+ } )
60
+ }
54
61
} ;
55
62
let html_content = parse_markdown ( raw_post. content ) ;
56
- let props = Post {
63
+ let post = Post {
57
64
title : raw_post. title ,
58
65
author : raw_post. author ,
59
66
content : html_content,
60
67
} ;
61
- Ok ( props )
68
+ Ok ( post )
62
69
}
63
70
#[ engine_only_fn]
64
- async fn get_build_paths ( ) -> RenderFnResult < BuildPaths > {
65
- Ok ( BuildPaths {
71
+ async fn get_build_paths ( ) -> BuildPaths {
72
+ BuildPaths {
66
73
// These will all become URLs at `/post/<name>`
67
74
paths : vec ! [
68
75
"welcome" . to_string( ) ,
@@ -71,12 +78,15 @@ async fn get_build_paths() -> RenderFnResult<BuildPaths> {
71
78
] ,
72
79
// Perseus supports helper state, but we don't need it here
73
80
extra : ( ) . into ( ) ,
74
- } )
81
+ }
75
82
}
76
83
// EXCERPT_END
77
84
78
85
// SNIP
79
- fn get_post_for_path ( _path : String ) -> Result < Post , std:: io:: Error > {
86
+ #[ derive( thiserror:: Error , Debug ) ]
87
+ #[ error( "an error!" ) ]
88
+ struct MyError ;
89
+ fn get_post_for_path ( _path : String ) -> Result < Post , io:: Error > {
80
90
unimplemented ! ( )
81
91
}
82
92
fn parse_markdown ( _content : String ) -> String {
0 commit comments