Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 97683a7

Browse files
Add support for filter chaining in filter blocks
1 parent a5c685d commit 97683a7

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

askama_derive/src/generator.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ use parser::node::{
1515
use parser::{Expr, Node};
1616
use quote::quote;
1717

18+
fn insert_variable_at_the_end(args: &mut Vec<Expr<'_>>, var_name: String) {
19+
if let Some(Expr::Filter(_, ref mut args)) = args.first_mut() {
20+
insert_variable_at_the_end(args, var_name);
21+
} else {
22+
args.insert(0, Expr::Generated(var_name.clone()));
23+
}
24+
}
25+
1826
pub(crate) struct Generator<'a> {
1927
// The template input state: original struct AST and attributes
2028
input: &'a TemplateInput<'a>,
@@ -736,10 +744,13 @@ impl<'a> Generator<'a> {
736744
mem::drop(mem::replace(&mut self.buf_writable, current_buf));
737745

738746
let mut filter_buf = Buffer::new(buf.indent);
739-
let mut args = filter.args.clone();
740-
args.insert(0, Expr::Generated(var_name.clone()));
747+
let (filter_name, mut args) = match &filter.filters {
748+
Expr::Filter(filter_name, args) => (filter_name, args.clone()),
749+
expr => panic!("Expected an `Expr::Filter`, found {expr:?}"),
750+
};
751+
insert_variable_at_the_end(&mut args, var_name.clone());
741752

742-
let wrap = self.visit_filter(&mut filter_buf, filter.filter_name, &args)?;
753+
let wrap = self.visit_filter(&mut filter_buf, filter_name, &args)?;
743754

744755
self.buf_writable
745756
.push(Writable::Generated(filter_buf.buf, wrap));

askama_parser/src/node.rs

+23-5
Original file line numberDiff line numberDiff line change
@@ -563,25 +563,44 @@ impl<'a> Macro<'a> {
563563
#[derive(Debug, PartialEq)]
564564
pub struct FilterBlock<'a> {
565565
pub ws1: Ws,
566-
pub filter_name: &'a str,
567-
pub args: Vec<Expr<'a>>,
566+
pub filters: Expr<'a>,
568567
pub nodes: Vec<Node<'a>>,
569568
pub ws2: Ws,
570569
}
571570

572571
impl<'a> FilterBlock<'a> {
573572
fn parse(i: &'a str, s: &State<'_>) -> ParseResult<'a, Self> {
573+
#[allow(clippy::type_complexity)]
574+
fn filter(i: &str, level: crate::Level) -> ParseResult<'_, (&str, Option<Vec<Expr<'_>>>)> {
575+
let (i, (_, fname, args)) = tuple((
576+
char('|'),
577+
ws(identifier),
578+
opt(|i| Expr::arguments(i, level, false)),
579+
))(i)?;
580+
Ok((i, (fname, args)))
581+
}
582+
574583
let mut start = tuple((
575584
opt(Whitespace::parse),
576585
ws(keyword("filter")),
577586
cut(tuple((
578587
ws(identifier),
579588
opt(|i| Expr::arguments(i, s.level.get(), false)),
589+
many0(|i| filter(i, s.level.get())),
580590
opt(Whitespace::parse),
581591
|i| s.tag_block_end(i),
582592
))),
583593
));
584-
let (i, (pws1, _, (filter_name, params, nws1, _))) = start(i)?;
594+
let (i, (pws1, _, (filter_name, params, extra_filters, nws1, _))) = start(i)?;
595+
596+
let mut filters = Expr::Filter(filter_name, params.unwrap_or_default());
597+
for (filter_name, args) in extra_filters {
598+
filters = Expr::Filter(filter_name, {
599+
let mut args = args.unwrap_or_default();
600+
args.insert(0, filters);
601+
args
602+
});
603+
}
585604

586605
let mut end = cut(tuple((
587606
|i| Node::many(i, s),
@@ -598,8 +617,7 @@ impl<'a> FilterBlock<'a> {
598617
i,
599618
Self {
600619
ws1: Ws(pws1, nws1),
601-
filter_name,
602-
args: params.unwrap_or_default(),
620+
filters,
603621
nodes,
604622
ws2: Ws(pws2, nws2),
605623
},

0 commit comments

Comments
 (0)