2024-04-11 08:49:26 +00: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-09 06:38:50 +00:00
|
|
|
println!("cargo:rerun-if-changed=migrations");
|
2024-04-11 08:49:26 +00: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-09 06:38:50 +00:00
|
|
|
}
|