roxy-markdown-tera-rewriter/src/lib.rs

129 lines
3.5 KiB
Rust

use std::io::Write;
use once_cell::sync::Lazy;
use regex::{Captures, Regex, RegexBuilder};
use roxy_core::roxy::Parse;
const PLACEHOLDER_RE: Lazy<Regex> = Lazy::new(|| {
RegexBuilder::new(r"^\n{0,2}(\s+)?(\{[\{|%].+?[\}|%]\})\r?\n{0,2}")
.multi_line(true)
.build()
.unwrap()
});
pub struct MarkdownTeraPreformatter;
impl MarkdownTeraPreformatter {
pub fn new() -> Self {
Self
}
}
impl Parse for MarkdownTeraPreformatter {
fn parse(&mut self, _path: &str, src: &[u8], dst: &mut Vec<u8>) -> Result<(), roxy_core::error::Error> {
let str = String::from_utf8_lossy(src).to_string();
let result = PLACEHOLDER_RE
.replace_all(str.as_str(), |captures: &Captures| {
format!("\n{}\n", &captures[2])
})
.trim()
.to_string();
dst.write_all(result.as_bytes())?;
Ok(())
}
}
const EXTENSION_RE: Lazy<Regex> = Lazy::new(|| {
RegexBuilder::new(r"^<p>(\{[%|\{].+?[%|\}]\}.*?)</p>")
.dot_matches_new_line(true)
.multi_line(true)
.build()
.unwrap()
});
pub struct MarkdownTeraRewriter;
impl MarkdownTeraRewriter {
pub fn new() -> Self {
Self
}
}
impl Parse for MarkdownTeraRewriter {
fn parse(&mut self, _path: &str, src: &[u8], dst: &mut Vec<u8>) -> Result<(), roxy_core::error::Error> {
let utf8 = String::from_utf8_lossy(src).to_string();
let result = EXTENSION_RE
.replace_all(utf8.as_str(), |captures: &Captures| {
format!("{}", &captures[1])
})
.replace("&quot;", "\"")
.to_string();
dst.write(result.as_bytes())?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use roxy_core::roxy::Parse;
use crate::{MarkdownTeraPreformatter, MarkdownTeraRewriter};
#[test]
fn basic_parse() {
let mut parser = MarkdownTeraRewriter::new();
let mut buf = Vec::new();
parser
.parse(
"test.html",
b"<p>{% extends \"base.html\" %}\n{% block content %}</p>\n<div><p>hi :3</p></div>{% endblock content %}",
&mut buf,
)
.unwrap();
assert_eq!(
"{% extends \"base.html\" %}\n{% block content %}\n<div><p>hi :3</p></div>{% endblock content %}",
String::from_utf8_lossy(&buf)
);
}
#[test]
fn import_parse() {
let mut parser = MarkdownTeraRewriter::new();
let mut buf = Vec::new();
parser
.parse(
"test.html",
b"<p>{% extends \"base.html\" %}\n{% import \"macros.html\" as macros %}\n{% block content %}</p>\n<div><p>hi :3</p></div>{% endblock content %}",
&mut buf,
)
.unwrap();
assert_eq!(
"{% extends \"base.html\" %}\n{% import \"macros.html\" as macros %}\n{% block content %}\n<div><p>hi :3</p></div>{% endblock content %}",
String::from_utf8_lossy(&buf)
);
}
#[test]
fn preformatter() {
let mut parser = MarkdownTeraPreformatter::new();
let mut buf = Vec::new();
parser
.parse(
"test.html",
b"{% extends \"base.html\" %}\n{% block content %}\n# hi :3\n{% endblock content %}",
&mut buf,
)
.unwrap();
assert_eq!(
"{% extends \"base.html\" %}\n\n{% block content %}\n# hi :3\n\n{% endblock content %}",
String::from_utf8_lossy(&buf)
);
}
}