Merge branch 'feature/rm-whitespace'

This commit is contained in:
Kogia-sima 2020-06-07 13:14:11 +09:00
commit 37c4e4d11d
10 changed files with 105 additions and 5 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -50,12 +50,14 @@ pub fn teams(b: &mut criterion::Bencher<'_>) {
#[derive(TemplateOnce)]
#[template(path = "big-table.stpl")]
#[template(rm_whitespace = true)]
struct BigTable<'a> {
table: &'a [Vec<usize>],
}
#[derive(TemplateOnce)]
#[template(path = "teams.stpl")]
#[template(rm_whitespace = true)]
struct TeamsTemplate<'a> {
year: u16,
teams: &'a [Team],

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -0,0 +1,13 @@
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<div>
trailing spaces
This line should be appeared under the previous line
</div>
<div>foo</div>
<div>bar</div>

View File

@ -0,0 +1,13 @@
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<div>
trailing spaces
This line should be appeared under the previous line
</div>
<% for msg in messages { %>
<div><%= msg %></div>
<% } %>

View File

@ -142,6 +142,18 @@ fn test_teams() {
assert_render("teams", teams);
}
#[derive(TemplateOnce)]
#[template(path = "rm_whitespace.stpl")]
#[template(rm_whitespace = true)]
struct RmWhitespace<'a, 'b> {
messages: &'a [&'b str],
}
#[test]
fn test_rm_whitespace() {
assert_render("rm_whitespace", RmWhitespace { messages: &["foo", "bar"] });
}
#[cfg(unix)]
mod unix {
use super::*;

View File

@ -45,7 +45,7 @@ impl Compiler {
});
let resolver = Resolver::new().include_handler(include_handler);
let optimizer = Optimizer::new();
let optimizer = Optimizer::new().rm_whitespace(self.config.rm_whitespace);
let compile_file = |input: &Path, output: &Path| -> Result<(), Error> {
let mut tsource = self.translate_file_contents(input)?;

View File

@ -5,6 +5,7 @@ pub struct Config {
pub delimiter: char,
pub escape: bool,
pub cache_dir: PathBuf,
pub rm_whitespace: bool,
#[doc(hidden)]
pub _non_exhaustive: ()
}
@ -15,6 +16,7 @@ impl Default for Config {
delimiter: '%',
escape: true,
cache_dir: Path::new(env!("OUT_DIR")).join("cache"),
rm_whitespace: false,
_non_exhaustive: ()
}
}

View File

@ -34,7 +34,9 @@ fn get_rendertext_value(i: &ExprMacro) -> Option<String> {
None
}
struct OptmizerImpl {}
struct OptmizerImpl {
rm_whitespace: bool,
}
impl VisitMut for OptmizerImpl {
fn visit_expr_mut(&mut self, i: &mut Expr) {
@ -84,18 +86,67 @@ impl VisitMut for OptmizerImpl {
*i = new_expr;
}
fn visit_expr_macro_mut(&mut self, i: &mut ExprMacro) {
if self.rm_whitespace {
if let Some(v) = get_rendertext_value(i) {
let mut buffer = String::new();
let mut it = v.lines().peekable();
if let Some(line) = it.next() {
if it.peek().is_some() {
buffer.push_str(line.trim_end());
buffer.push('\n');
} else {
return;
}
}
while let Some(line) = it.next() {
if it.peek().is_some() {
if !line.is_empty() {
buffer.push_str(line.trim());
buffer.push('\n');
} else {
// ignore empty line
}
} else {
// last line
buffer.push_str(line.trim_start());
}
}
i.mac.tokens = quote! { _ctx, #buffer };
return;
}
}
syn::visit_mut::visit_expr_macro_mut(self, i);
}
}
pub struct Optimizer {}
pub struct Optimizer {
rm_whitespace: bool,
}
impl Optimizer {
#[inline]
pub fn new() -> Self {
Self {}
Self {
rm_whitespace: false,
}
}
#[inline]
pub fn rm_whitespace(mut self, new: bool) -> Self {
self.rm_whitespace = new;
self
}
#[inline]
pub fn optimize(&self, i: &mut Block) {
OptmizerImpl {}.visit_block_mut(i);
OptmizerImpl {
rm_whitespace: self.rm_whitespace,
}
.visit_block_mut(i);
}
}

View File

@ -30,6 +30,7 @@ struct DeriveTemplateOptions {
path: Option<LitStr>,
delimiter: Option<LitChar>,
escape: Option<LitBool>,
rm_whitespace: Option<LitBool>,
type_: Option<LitStr>,
}
@ -59,6 +60,8 @@ impl Parse for DeriveTemplateOptions {
options.delimiter = Some(s.parse::<LitChar>()?);
} else if key == "escape" {
options.escape = Some(s.parse::<LitBool>()?);
} else if key == "rm_whitespace" {
options.rm_whitespace = Some(s.parse::<LitBool>()?);
} else if key == "type" {
options.type_ = Some(s.parse::<LitStr>()?);
} else {
@ -103,6 +106,7 @@ impl DeriveTemplateOptions {
merge_single(&mut self.path, other.path)?;
merge_single(&mut self.delimiter, other.delimiter)?;
merge_single(&mut self.escape, other.escape)?;
merge_single(&mut self.rm_whitespace, other.rm_whitespace)?;
merge_single(&mut self.type_, other.type_)?;
Ok(())
}
@ -125,6 +129,9 @@ fn compile(
if let Some(ref escape) = options.escape {
config.escape = escape.value;
}
if let Some(ref rm_whitespace) = options.rm_whitespace {
config.rm_whitespace = rm_whitespace.value;
}
let compiler = Compiler::with_config(config);
compiler.compile_file(template_dir, input_file, &*output_file)