@@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize};
2222use std:: fmt;
2323
2424lazy_static ! {
25- static refBLOG : Collection =Collection :: new(
25+ pub static refBLOG : Collection =Collection :: new(
2626"Blog" ,
2727true ,
2828HashMap :: from( [
@@ -93,7 +93,7 @@ impl FromStr for DocType {
9393}
9494}
9595
96- #[ derive( Debug , Serialize , Deserialize ) ]
96+ #[ derive( Debug , Serialize , Deserialize , Default ) ]
9797pub struct Document {
9898/// The absolute path on disk
9999pub path : PathBuf ,
@@ -110,10 +110,15 @@ pub struct Document {
110110pub doc_type : Option < DocType > ,
111111// url to thumbnail for social share
112112pub thumbnail : Option < String > ,
113+ pub url : String ,
113114}
114115
115116// Gets document markdown
116117impl Document {
118+ pub fn new ( ) ->Document {
119+ Document { ..Default :: default ( ) }
120+ }
121+
117122pub async fn from_path ( path : & PathBuf ) -> anyhow:: Result < Document , std:: io:: Error > {
118123let doc_type =match path. strip_prefix ( config:: cms_dir ( ) ) {
119124Ok ( path) =>match path. into_iter ( ) . next ( ) {
@@ -151,11 +156,14 @@ impl Document {
151156( None , contents)
152157} ;
153158
154- let default_image_path =BLOG
155- . asset_url_root
156- . join ( "blog_image_placeholder.png" )
157- . display ( )
158- . to_string ( ) ;
159+ let default_image_path =match doc_type{
160+ Some ( DocType :: Blog ) =>BLOG
161+ . asset_url_root
162+ . join ( "blog_image_placeholder.png" )
163+ . display ( )
164+ . to_string ( ) ,
165+ _ =>String :: from ( "/dashboard/static/images/careers_article_default.png" ) ,
166+ } ;
159167
160168// parse meta section
161169let ( description, image, featured, tags) =match meta{
@@ -166,15 +174,20 @@ impl Document {
166174Some ( meta[ "description" ] . as_str ( ) . unwrap ( ) . to_string ( ) )
167175} ;
168176
169- // For now the only images shown are blog images TODO: use doc_type to set asset path when working.
170177let image =if meta[ "image" ] . is_badvalue ( ) {
171178Some ( default_image_path. clone ( ) )
172179} else {
173180match PathBuf :: from_str ( meta[ "image" ] . as_str ( ) . unwrap ( ) ) {
174181Ok ( image_path) =>match image_path. file_name ( ) {
175182Some ( file_name) =>{
176183let file =PathBuf :: from ( file_name) . display ( ) . to_string ( ) ;
177- Some ( BLOG . asset_url_root . join ( file) . display ( ) . to_string ( ) )
184+ match doc_type{
185+ Some ( DocType :: Docs ) =>Some ( DOCS . asset_url_root . join ( file) . display ( ) . to_string ( ) ) ,
186+ Some ( DocType :: Careers ) =>{
187+ Some ( CAREERS . asset_url_root . join ( file) . display ( ) . to_string ( ) )
188+ }
189+ _ =>Some ( BLOG . asset_url_root . join ( file) . display ( ) . to_string ( ) ) ,
190+ }
178191}
179192 _ =>Some ( default_image_path. clone ( ) ) ,
180193} ,
@@ -221,6 +234,34 @@ impl Document {
221234let toc_links =crate :: utils:: markdown:: get_toc ( root) . unwrap ( ) ;
222235let ( author, date, author_image) =crate :: utils:: markdown:: get_author ( root) ;
223236
237+ // convert author image relative url path to absolute url path
238+ let author_image =if author_image. is_some ( ) {
239+ let image = author_image. clone ( ) . unwrap ( ) ;
240+ let image =PathBuf :: from ( image) ;
241+ let image = image. file_name ( ) . unwrap ( ) ;
242+ match & doc_type{
243+ Some ( DocType :: Blog ) =>Some ( BLOG . asset_url_root . join ( image. to_str ( ) . unwrap ( ) ) . display ( ) . to_string ( ) ) ,
244+ Some ( DocType :: Docs ) =>Some ( DOCS . asset_url_root . join ( image. to_str ( ) . unwrap ( ) ) . display ( ) . to_string ( ) ) ,
245+ Some ( DocType :: Careers ) =>Some (
246+ CAREERS
247+ . asset_url_root
248+ . join ( PathBuf :: from ( image. to_str ( ) . unwrap ( ) ) )
249+ . display ( )
250+ . to_string ( ) ,
251+ ) ,
252+ _ =>None ,
253+ }
254+ } else {
255+ None
256+ } ;
257+
258+ let url =match doc_type{
259+ Some ( DocType :: Blog ) =>BLOG . path_to_url ( & path) ,
260+ Some ( DocType :: Docs ) =>DOCS . path_to_url ( & path) ,
261+ Some ( DocType :: Careers ) =>CAREERS . path_to_url ( & path) ,
262+ _ =>String :: new ( ) ,
263+ } ;
264+
224265let document =Document {
225266path : path. to_owned ( ) ,
226267 description,
@@ -235,6 +276,7 @@ impl Document {
235276 contents,
236277 doc_type,
237278 thumbnail,
279+ url,
238280} ;
239281Ok ( document)
240282}
@@ -478,6 +520,25 @@ impl Collection {
478520self . root_dir . join ( path_pb)
479521}
480522
523+ // Convert a file path to a url
524+ pub fn path_to_url ( & self , path : & PathBuf ) ->String {
525+ let url = path. strip_prefix ( config:: cms_dir ( ) ) . unwrap ( ) ;
526+ let url =format ! ( "/{}" , url. display( ) . to_string( ) ) ;
527+
528+ let url =if url. ends_with ( "README.md" ) {
529+ url. replace ( "README.md" , "" )
530+ } else {
531+ url
532+ } ;
533+
534+ let url =if url. ends_with ( ".md" ) {
535+ url. replace ( ".md" , "" )
536+ } else {
537+ url
538+ } ;
539+ url
540+ }
541+
481542// get all urls in the collection and preserve order.
482543pub fn get_all_urls ( & self ) ->Vec < String > {
483544let mut urls: Vec < String > =Vec :: new ( ) ;
@@ -524,35 +585,39 @@ impl Collection {
524585) ->Result < ResponseOk , crate :: responses:: NotFound > {
525586match Document :: from_path ( & path) . await {
526587Ok ( doc) =>{
527- let mut layout =crate :: templates:: Layout :: new ( & doc. title , Some ( cluster) ) ;
528- if let Some ( image) =& doc. thumbnail {
529- layout. image ( & image) ;
530- }
531- if let Some ( description) =& doc. description {
532- layout. description ( description) ;
533- }
588+ let head =crate :: components:: layouts:: Head :: new ( )
589+ . title ( & doc. title )
590+ . description ( & doc. description . clone ( ) . unwrap_or_else ( ||String :: new ( ) ) )
591+ . image ( & doc. thumbnail . clone ( ) . unwrap_or_else ( ||String :: new ( ) ) )
592+ . canonical ( & canonical) ;
534593
535- let layout =layout . canonical ( canonical ) . toc_links ( & doc . toc_links ) ;
594+ let layout =Base :: from_head ( head , Some ( cluster ) ) . theme ( Theme :: Docs ) ;
536595
537- Ok ( ResponseOk (
538- layout. render ( crate :: templates:: Article { content : doc. html ( ) } ) ,
539- ) )
596+ let mut article =crate :: components:: pages:: article:: Index :: new ( & cluster)
597+ . document ( doc)
598+ . await ;
599+
600+ article =if self . name =="Blog" {
601+ article. is_blog ( )
602+ } else {
603+ article. is_careers ( )
604+ } ;
605+
606+ Ok ( ResponseOk ( layout. render ( article) ) )
540607}
541608// Return page not found on bad path
542609 _ =>{
543- let mut layout =crate :: templates:: Layout :: new ( "404" , Some ( cluster) ) ;
544-
545- let doc =String :: from (
546- r#"
547- <div style='height: 80vh'>
548- <h2>Oops, document not found!</h2>
549- <p>The document you are searching for may have been moved or replaced with better content.</p>
550- </div>"# ,
551- ) ;
552-
553- Err ( crate :: responses:: NotFound (
554- layout. render ( crate :: templates:: Article { content : doc} ) . into ( ) ,
555- ) )
610+ let layout =Base :: new ( "404" , Some ( cluster) ) . theme ( Theme :: Docs ) ;
611+
612+ let mut article =crate :: components:: pages:: article:: Index :: new ( & cluster) . document_not_found ( ) ;
613+
614+ article =if self . name =="Blog" {
615+ article. is_blog ( )
616+ } else {
617+ article. is_careers ( )
618+ } ;
619+
620+ Err ( crate :: responses:: NotFound ( layout. render ( article) ) )
556621}
557622}
558623}