2024-04-11 01:49:26 -07:00
use regex ::Regex ;
use std ::{ collections ::HashSet , env , error ::Error , fs , path ::Path , process ::Command } ;
fn escape_template ( v : & str ) -> Result < String , String > {
let cant_escape = " \\ { " ;
if v . contains ( cant_escape ) {
return Err ( format! ( " can't escape {cant_escape} " ) ) ;
}
Ok ( v . replace ( " { " , " \\ { " ) )
}
fn main ( ) -> Result < ( ) , Box < dyn Error > > {
2024-04-08 23:38:50 -07:00
println! ( " cargo:rerun-if-changed=migrations " ) ;
2024-04-11 01:49:26 -07:00
println! ( " cargo:rerun-if-changed=website " ) ;
let out_dir = env ::var_os ( " OUT_DIR " ) . unwrap ( ) ;
let website_dir = Path ::new ( & out_dir ) . join ( " website " ) ;
let templates_dir = Path ::new ( & out_dir ) . join ( " templates " ) ;
fs ::create_dir_all ( & templates_dir ) ? ;
let status = Command ::new ( " mdbook " )
. arg ( " build " )
. arg ( " --dest-dir " )
. arg ( & website_dir )
. current_dir ( " website " )
. status ( )
. map_err ( | e | format! ( " Can't run mdbook: {e} " ) ) ? ;
if ! status . success ( ) {
return Err ( format! ( " mdbook exited with an error: {status:?} " ) . into ( ) ) ;
}
let sub_template_path = website_dir . join ( " subscription/index.html " ) ;
let sub_template = fs ::read_to_string ( & sub_template_path )
. map_err ( | e | format! ( " Error reading {} : {e} " , sub_template_path . display ( ) ) ) ? ;
let regex = Regex ::new ( r # "(?s)<div class="subscribe_list_template_section" id="(?<id>[^"]*)"/>(?<template>.*?)<div class="subscribe_list_template_section"/>"# ) . unwrap ( ) ;
let matches = Vec ::from_iter ( regex . captures_iter ( & sub_template ) ) ;
let mut between_matches = vec! [ ] ;
let mut last_end = 0 ;
for m in & matches {
let m = m . get ( 0 ) . unwrap ( ) ;
between_matches . push ( & sub_template [ last_end .. m . start ( ) ] ) ;
last_end = m . end ( ) ;
}
between_matches . push ( & sub_template [ last_end .. ] ) ;
let prefix = between_matches . remove ( 0 ) ;
let Some ( suffix ) = between_matches . pop ( ) else {
return Err ( format! (
" no subscribe_list_template_section `div`s found: {} " ,
sub_template_path . display ( )
)
. into ( ) ) ;
} ;
let prefix = escape_template ( prefix ) ? ;
let suffix = escape_template ( suffix ) ? ;
for i in between_matches {
if i . trim_start ( ) ! = " " {
return Err ( format! (
r #" can't have non-whitespace text between
< div class = " subscribe_list_template_section " / >
and next
< div class = " subscribe_list_template_section " id = " .. " > " #
)
. into ( ) ) ;
}
}
let mut identifiers = HashSet ::new ( ) ;
for m in & matches {
let id = & m [ " id " ] ;
if id . contains ( | ch : char | ! ch . is_ascii_alphanumeric ( ) & & ch ! = '_' ) {
return Err ( format! ( " invalid identifier {id:?} " ) . into ( ) ) ;
}
if ! identifiers . insert ( id ) {
return Err ( format! ( " duplicate identifier {id:?} " ) . into ( ) ) ;
}
let template = & m [ " template " ] ;
fs ::write (
templates_dir . join ( format! ( " {id} .txt " ) ) ,
prefix . clone ( ) + template + & suffix ,
) ? ;
}
Ok ( ( ) )
2024-04-08 23:38:50 -07:00
}