#![warn(missing_docs)]
pub mod error;
use crate::error::*;
use regex::Regex;
use std::{cell::OnceCell, fs, path::Path};
pub struct LyWebpage {
pub contents: String,
}
impl LyWebpage {
pub fn from_str(s: &str) -> Self {
Self { contents: s.to_string() }
}
pub fn from_file<P: AsRef<Path>>(filepath: P) -> Result<Self, LyError> {
Ok(Self::from_str(&fs::read_to_string(filepath)?))
}
pub fn fill_with_str(mut self, key: &str, contents: &str) -> Self {
self.contents = self.contents.replace(&format!("[[{key}]]"), contents);
self
}
pub fn fill_from_md_str(self, key: &str, md: &str, gfm: bool) -> Self {
use markdown::{to_html, to_html_with_options, Options};
let html = if gfm {
to_html_with_options(md, &Options::gfm()).unwrap_or(md.to_string())
} else {
to_html(md)
};
self.fill_with_str(key, &html)
}
pub fn fill_from_file<P: AsRef<Path>>(self, key: &str, filepath: P) -> Result<Self, LyError> {
Ok(self.fill_with_str(key, &fs::read_to_string(filepath)?))
}
pub fn fill_from_md_file<P: AsRef<Path>>(self, key: &str, filepath: P, gfm: bool) -> Result<Self, LyError> {
let md = fs::read_to_string(filepath)?;
Ok(self.fill_from_md_str(key, &md, gfm))
}
pub fn resolve_ifs(mut self, path: &str) -> Result<Self, LyError> {
let re_cell = OnceCell::new();
let re = match re_cell.get() {
Some(r) => r,
None => {
let r = Regex::new(r#"(?s)\[\[\s*IF\s+(\S+)(.*?)ELSE\s+(.*?)\]\]"#)?;
let _ = re_cell.set(r);
re_cell.get().ok_or(LyError::TemplatingError)?
}
};
let mut locs = re.capture_locations();
macro_rules! loc {
( $i:expr ) => {
locs.get($i).ok_or(LyError::TemplatingError)?
};
}
let mut s = String::new();
let mut i = 0;
while let Some(_) = re.captures_read_at(&mut locs, &self.contents, i) {
s += &self.contents[i..loc!(0).0];
if path == &self.contents[loc!(1).0..loc!(1).1] {
s += &self.contents[loc!(2).0..loc!(2).1];
} else {
s += &self.contents[loc!(3).0..loc!(3).1];
}
i = loc!(0).1;
}
s += &self.contents[i..];
self.contents = s;
Ok(self)
}
}
#[cfg(test)]
mod tests {
use crate::*;
fn remove_whitespace(s: &mut String) {
s.retain(|c| !c.is_whitespace())
}
#[test]
fn files() {
let mut page = LyWebpage::from_file("test/template.html").unwrap()
.fill_from_file("content", "test/content.html").unwrap()
.resolve_ifs("blog").unwrap()
.contents;
remove_whitespace(&mut page);
assert_eq!(page, "<html><body><h1>Blog</h1><p>testing!</p></body></html>");
}
#[test]
fn md_works() {
let mut page = LyWebpage::from_str("<div>[[markdown]]</div>")
.fill_from_md_str("markdown", "# HEADER", true)
.contents;
remove_whitespace(&mut page);
assert_eq!(page, "<div><h1>HEADER</h1></div>");
}
}