Skip to content

Commit ec05c62

Browse files
add closing tag and adjust branching strat
1 parent 0ea2dea commit ec05c62

11 files changed

+213
-215
lines changed

crates/djls-template-ast/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ pub enum TagNode {
6363

6464
#[derive(Clone, Debug, Serialize)]
6565
pub struct DjangoFilter {
66-
pub name: String,
67-
pub arguments: Vec<String>,
66+
name: String,
67+
arguments: Vec<String>,
6868
}
6969

7070
impl DjangoFilter {

crates/djls-template-ast/src/parser.rs

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -155,22 +155,28 @@ impl Parser {
155155

156156
let specs = TagSpec::load_builtin_specs().unwrap_or_default();
157157

158-
// Check if closing or intermediate tag according to any spec
158+
// Check if this is a closing tag
159159
for (_, spec) in specs.iter() {
160160
if Some(&tag_name) == spec.closing.as_ref() {
161+
let node = Node::Django(DjangoNode::Tag(TagNode::Closing {
162+
name: tag_name.clone(),
163+
bits: bits[1..].to_vec(),
164+
}));
161165
return Err(ParserError::ErrorSignal(Signal::SpecialTag(tag_name)));
162166
}
167+
}
168+
169+
// Check if this is a branch tag according to any spec
170+
for (_, spec) in specs.iter() {
163171
if let Some(intermediates) = &spec.intermediates {
164-
if intermediates.contains(&tag_name) {
172+
if intermediates.iter().any(|i| i.name == tag_name) {
165173
return Err(ParserError::ErrorSignal(Signal::SpecialTag(tag_name)));
166174
}
167175
}
168176
}
169177

170178
let tag_spec = specs.get(tag_name.as_str()).cloned();
171-
172179
let mut children = Vec::new();
173-
let mut branches = Vec::new();
174180

175181
while !self.is_at_end() {
176182
match self.next_node() {
@@ -181,40 +187,44 @@ impl Parser {
181187
if let Some(spec) = &tag_spec {
182188
// Check if closing tag
183189
if Some(&tag) == spec.closing.as_ref() {
184-
let tag_node = if !branches.is_empty() {
185-
TagNode::Branching {
186-
name: tag_name,
187-
bits,
188-
children,
189-
branches,
190-
}
191-
} else {
192-
TagNode::Block {
193-
name: tag_name,
194-
bits,
195-
children,
196-
}
197-
};
198-
return Ok(Node::Django(DjangoNode::Tag(tag_node)));
190+
children.push(Node::Django(DjangoNode::Tag(TagNode::Closing {
191+
name: tag,
192+
bits: vec![],
193+
})));
194+
return Ok(Node::Django(DjangoNode::Tag(TagNode::Block {
195+
name: tag_name,
196+
bits,
197+
children,
198+
})));
199199
}
200200
// Check if intermediate tag
201201
if let Some(intermediates) = &spec.intermediates {
202-
if intermediates.contains(&tag) {
203-
branches.push(TagNode::Block {
204-
name: tag.clone(),
205-
bits: vec![tag.clone()],
206-
children,
207-
});
208-
children = Vec::new();
202+
if let Some(intermediate) = intermediates.iter().find(|i| i.name == tag) {
203+
// Create branch node with the current children
204+
let branch_bits = if intermediate.args {
205+
match &self.tokens[self.current - 1].token_type() {
206+
TokenType::DjangoBlock(content) => content
207+
.split_whitespace()
208+
.skip(1) // Skip the tag name
209+
.map(|s| s.to_string())
210+
.collect(),
211+
_ => vec![tag.clone()],
212+
}
213+
} else {
214+
vec![]
215+
};
216+
children.push(Node::Django(DjangoNode::Tag(TagNode::Branch {
217+
name: tag,
218+
bits: branch_bits,
219+
children: Vec::new(),
220+
})));
209221
continue;
210222
}
211223
}
212224
}
213225
return Err(ParserError::UnexpectedTag(tag));
214226
}
215-
Err(e) => {
216-
return Err(e);
217-
}
227+
Err(e) => return Err(e),
218228
}
219229
}
220230

crates/djls-template-ast/src/snapshots/djls_template_ast__parser__tests__django__parse_complex_if_elif.snap

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,34 @@ expression: ast
55
nodes:
66
- Django:
77
Tag:
8-
Branching:
8+
Block:
99
name: if
1010
bits:
1111
- if
1212
- x
1313
- ">"
1414
- "0"
1515
children:
16+
- Text: Positive
17+
- Django:
18+
Tag:
19+
Branch:
20+
name: elif
21+
bits:
22+
- x
23+
- "<"
24+
- "0"
25+
children: []
26+
- Text: Negative
27+
- Django:
28+
Tag:
29+
Branch:
30+
name: else
31+
bits: []
32+
children: []
1633
- Text: Zero
17-
branches:
18-
- Block:
19-
name: elif
20-
bits:
21-
- elif
22-
children:
23-
- Text: Positive
24-
- Block:
25-
name: else
26-
bits:
27-
- else
28-
children:
29-
- Text: Negative
34+
- Django:
35+
Tag:
36+
Closing:
37+
name: endif
38+
bits: []

crates/djls-template-ast/src/snapshots/djls_template_ast__parser__tests__django__parse_django_for_block.snap

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,28 @@ expression: ast
55
nodes:
66
- Django:
77
Tag:
8-
Branching:
8+
Block:
99
name: for
1010
bits:
1111
- for
1212
- item
1313
- in
1414
- items
1515
children:
16+
- Django:
17+
Variable:
18+
bits:
19+
- item
20+
filters: []
21+
- Django:
22+
Tag:
23+
Branch:
24+
name: empty
25+
bits: []
26+
children: []
1627
- Text: No items
17-
branches:
18-
- Block:
19-
name: empty
20-
bits:
21-
- empty
22-
children:
23-
- Django:
24-
Variable:
25-
bits:
26-
- item
27-
filters: []
28+
- Django:
29+
Tag:
30+
Closing:
31+
name: endfor
32+
bits: []

crates/djls-template-ast/src/snapshots/djls_template_ast__parser__tests__django__parse_django_if_block.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ nodes:
1212
- user.is_authenticated
1313
children:
1414
- Text: Welcome
15+
- Django:
16+
Tag:
17+
Closing:
18+
name: endif
19+
bits: []

crates/djls-template-ast/src/snapshots/djls_template_ast__parser__tests__django__parse_mixed_content.snap

Lines changed: 94 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -6,79 +6,104 @@ nodes:
66
- Text: "Welcome, "
77
- Django:
88
Tag:
9-
Branching:
9+
Block:
1010
name: if
1111
bits:
1212
- if
1313
- user.is_authenticated
1414
children:
15+
- Django:
16+
Variable:
17+
bits:
18+
- user
19+
- name
20+
filters:
21+
- name: title
22+
arguments: []
23+
- name: default
24+
arguments:
25+
- "'Guest'"
26+
- Django:
27+
Tag:
28+
Block:
29+
name: for
30+
bits:
31+
- for
32+
- group
33+
- in
34+
- user.groups
35+
children:
36+
- Django:
37+
Tag:
38+
Block:
39+
name: if
40+
bits:
41+
- if
42+
- forloop.first
43+
children:
44+
- Text: (
45+
- Django:
46+
Tag:
47+
Closing:
48+
name: endif
49+
bits: []
50+
- Django:
51+
Variable:
52+
bits:
53+
- group
54+
- name
55+
filters: []
56+
- Django:
57+
Tag:
58+
Block:
59+
name: if
60+
bits:
61+
- if
62+
- not
63+
- forloop.last
64+
children:
65+
- Text: ", "
66+
- Django:
67+
Tag:
68+
Closing:
69+
name: endif
70+
bits: []
71+
- Django:
72+
Tag:
73+
Block:
74+
name: if
75+
bits:
76+
- if
77+
- forloop.last
78+
children:
79+
- Text: )
80+
- Django:
81+
Tag:
82+
Closing:
83+
name: endif
84+
bits: []
85+
- Django:
86+
Tag:
87+
Branch:
88+
name: empty
89+
bits: []
90+
children: []
91+
- Text: (no groups)
92+
- Django:
93+
Tag:
94+
Closing:
95+
name: endfor
96+
bits: []
97+
- Django:
98+
Tag:
99+
Branch:
100+
name: else
101+
bits: []
102+
children: []
15103
- Text: Guest
16-
branches:
17-
- Block:
18-
name: else
19-
bits:
20-
- else
21-
children:
22-
- Django:
23-
Variable:
24-
bits:
25-
- user
26-
- name
27-
filters:
28-
- name: title
29-
arguments: []
30-
- name: default
31-
arguments:
32-
- "'Guest'"
33-
- Django:
34-
Tag:
35-
Branching:
36-
name: for
37-
bits:
38-
- for
39-
- group
40-
- in
41-
- user.groups
42-
children:
43-
- Text: (no groups)
44-
branches:
45-
- Block:
46-
name: empty
47-
bits:
48-
- empty
49-
children:
50-
- Django:
51-
Tag:
52-
Block:
53-
name: if
54-
bits:
55-
- if
56-
- forloop.first
57-
children:
58-
- Text: (
59-
- Django:
60-
Variable:
61-
bits:
62-
- group
63-
- name
64-
filters: []
65-
- Django:
66-
Tag:
67-
Block:
68-
name: if
69-
bits:
70-
- if
71-
- not
72-
- forloop.last
73-
children:
74-
- Text: ", "
75-
- Django:
76-
Tag:
77-
Block:
78-
name: if
79-
bits:
80-
- if
81-
- forloop.last
82-
children:
83-
- Text: )
104+
- Django:
105+
Tag:
106+
Closing:
107+
name: endif
108+
bits: []
84109
- Text: "!"

0 commit comments

Comments
 (0)