66
77use std:: process:: ExitCode ;
88
9+ use anyhow:: { Context as _, bail} ;
10+ use camino:: Utf8PathBuf ;
911use clap:: Parser ;
1012use figment:: Figment ;
1113use mas_config:: {
@@ -27,14 +29,19 @@ pub(super) struct Options {
2729#[ derive( Parser , Debug ) ]
2830enum Subcommand {
2931 /// Check that the templates specified in the config are valid
30- Check ,
32+ Check {
33+ /// If set, templates will be rendered to this directory.
34+ /// The directory must either not exist or be empty.
35+ #[ arg( long = "out-dir" ) ]
36+ out_dir : Option < Utf8PathBuf > ,
37+ } ,
3138}
3239
3340impl Options {
3441 pub async fn run ( self , figment : & Figment ) -> anyhow:: Result < ExitCode > {
3542 use Subcommand as SC ;
3643 match self . subcommand {
37- SC :: Check => {
44+ SC :: Check { out_dir } => {
3845 let _span = info_span ! ( "cli.templates.check" ) . entered ( ) ;
3946
4047 let template_config = TemplatesConfig :: extract_or_default ( figment)
@@ -67,7 +74,39 @@ impl Options {
6774 ) ?;
6875 let templates =
6976 templates_from_config ( & template_config, & site_config, & url_builder) . await ?;
70- templates. check_render ( clock. now ( ) , & mut rng) ?;
77+ let all_renders = templates. check_render ( clock. now ( ) , & mut rng) ?;
78+
79+ if let Some ( out_dir) = out_dir {
80+ // Save renders to disk.
81+ if out_dir. exists ( ) {
82+ let mut read_dir =
83+ tokio:: fs:: read_dir ( & out_dir) . await . with_context ( || {
84+ format ! ( "could not read {out_dir} to check it's empty" )
85+ } ) ?;
86+ while let Some ( x) = read_dir. next_entry ( ) . await ? {
87+ bail ! ( "Render directory {out_dir} is not empty, refusing to write." ) ;
88+ }
89+ } else {
90+ tokio:: fs:: create_dir ( & out_dir)
91+ . await
92+ . with_context ( || format ! ( "could not create {out_dir}" ) ) ?;
93+ }
94+
95+ for ( template, template_renders) in & all_renders {
96+ let template_filename_base =
97+ template. trim_end_matches ( ".html" ) . replace ( '/' , "_" ) ;
98+ for ( idx, render) in template_renders. iter ( ) . enumerate ( ) {
99+ let render_path =
100+ out_dir. join ( format ! ( "{template_filename_base}-sample{idx}.html" ) ) ;
101+
102+ tokio:: fs:: write ( & render_path, render. as_bytes ( ) )
103+ . await
104+ . with_context ( || {
105+ format ! ( "could not write render to {render_path}" )
106+ } ) ?;
107+ }
108+ }
109+ }
71110
72111 Ok ( ExitCode :: SUCCESS )
73112 }
0 commit comments