Compare commits

...

5 commits

Author SHA1 Message Date
KitsuneCafe 13868747c2 search for nested includes 2024-02-05 17:07:42 -05:00
KitsuneCafe 38e161ae3d handle nested includes/extends 2024-02-05 15:48:17 -05:00
KitsuneCafe 06c9e87041 iterate captures 2024-02-05 15:37:56 -05:00
KitsuneCafe 2b2171c61d all captures 2024-02-05 15:26:54 -05:00
KitsuneCafe 6084b9072b handle template includes 2024-02-05 15:21:49 -05:00
4 changed files with 51 additions and 17 deletions

View file

@ -1,12 +1,17 @@
use std::path::PathBuf; use std::{
fs::{self, read, File},
io::BufReader,
path::{Path, PathBuf},
};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use roxy_core::roxy::Parse; use roxy_core::roxy::Parse;
const DEFAULT_CONTEXT: Lazy<tera::Context> = Lazy::new(|| tera::Context::default()); const DEFAULT_CONTEXT: Lazy<tera::Context> = Lazy::new(|| tera::Context::default());
const EXPANSION_RE: Lazy<Regex> = const EXPANSION_RE: Lazy<Regex> = Lazy::new(|| {
Lazy::new(|| Regex::new("\\{% extends \"?(.+?)\"? %\\}").expect("couldn't load regex")); Regex::new("\\{% (extends|include) \"?(.+?)\"? %\\}").expect("couldn't load regex")
});
#[derive(Debug)] #[derive(Debug)]
pub struct TeraParserOptions { pub struct TeraParserOptions {
@ -41,18 +46,24 @@ impl<'a> TeraParser<'a> {
self.context = Some(context); self.context = Some(context);
} }
fn load_template(&mut self, path: &str, src: &[u8]) -> Result<(), tera::Error> { fn load_template<P: AsRef<Path>>(&mut self, path: &P, src: &[u8]) -> Result<(), tera::Error> {
let path = path.as_ref().canonicalize()?;
let str = String::from_utf8_lossy(src).to_string(); let str = String::from_utf8_lossy(src).to_string();
if let Some(captures) = EXPANSION_RE.captures(&str.as_str()) { for (_, [_, layout_path]) in EXPANSION_RE
if let Some(layout_path) = captures.get(1) { .captures_iter(&str.as_str())
let layout_path = layout_path.as_str(); .map(|c| c.extract())
let path = PathBuf::from(path).parent().map(|p| p.join(layout_path)).unwrap(); {
let path = path
.canonicalize()?
.parent()
.map(|p| p.join(layout_path))
.unwrap();
self.tera.add_template_file( let next_template = fs::read(&path)?;
&path.canonicalize().unwrap(), self.load_template(&path, &next_template)?;
Some(layout_path)
)?; self.tera
} .add_template_file(&path, Some(layout_path))?;
} }
Ok(()) Ok(())
@ -60,7 +71,12 @@ impl<'a> TeraParser<'a> {
} }
impl<'a> Parse for TeraParser<'a> { impl<'a> Parse for TeraParser<'a> {
fn parse(&mut self, path: &str, src: &[u8], dst: &mut Vec<u8>) -> Result<(), roxy_core::error::Error> { fn parse(
&mut self,
path: &str,
src: &[u8],
dst: &mut Vec<u8>,
) -> Result<(), roxy_core::error::Error> {
// TODO: This error is a hack // TODO: This error is a hack
let err = |e: tera::Error| { let err = |e: tera::Error| {
println!("{e:?}"); println!("{e:?}");
@ -68,7 +84,7 @@ impl<'a> Parse for TeraParser<'a> {
}; };
if self.options.auto_load_layouts { if self.options.auto_load_layouts {
self.load_template(path, src).map_err(err)?; self.load_template(&path, src).map_err(err)?;
} }
let template = String::from_utf8_lossy(src).to_string(); let template = String::from_utf8_lossy(src).to_string();
@ -87,6 +103,19 @@ impl<'a> Parse for TeraParser<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] use std::fs;
fn it_works() {}
use roxy_core::roxy::Parse;
use crate::{TeraParser, TeraParserOptions};
//#[test]
//fn capture_test() {
// let mut tera = tera::Tera::default();
// let mut parser = TeraParser::new(&mut tera, TeraParserOptions::default());
// let data = fs::read("./tests/index.md").unwrap();
// let mut dst = Vec::new();
// parser.parse("./tests/index.md", &data, &mut dst);
// println!("{dst:?}");
//}
} }

1
tests/base.html Normal file
View file

@ -0,0 +1 @@
:3

2
tests/index.md Normal file
View file

@ -0,0 +1,2 @@
{% extends "middle.html" %}

2
tests/middle.html Normal file
View file

@ -0,0 +1,2 @@
{% extends "base.html" %}