Skip to content

Commit 134f3fe

Browse files
fix parseing of django tags with potential intermediates
1 parent a5e42fe commit 134f3fe

File tree

2 files changed

+141
-4
lines changed

2 files changed

+141
-4
lines changed

crates/djls-ast/src/parser.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,18 @@ impl Parser {
155155
if tag == end_tag {
156156
self.consume()?;
157157
break;
158+
} else if !tag.starts_with("end") {
159+
// For intermediate tags (else, elif, empty, etc.)
160+
self.consume()?;
161+
// Create a new Tag node for the intermediate tag
162+
children.push(Node::Django(DjangoNode::Tag {
163+
kind: DjangoTagKind::from_str(&tag)?,
164+
bits: vec![tag.clone()],
165+
children: Vec::new(),
166+
}));
167+
} else {
168+
return Err(ParserError::ErrorSignal(Signal::ClosingTagFound(tag)));
158169
}
159-
// If it's not our end tag, keep collecting children
160170
}
161171
Err(e) => return Err(e),
162172
}
@@ -453,16 +463,37 @@ impl Parser {
453463
const SYNC_TYPES: &[TokenType] = &[
454464
TokenType::DjangoBlock(String::new()),
455465
TokenType::HtmlTagOpen(String::new()),
466+
TokenType::HtmlTagClose(String::new()), // Added
456467
TokenType::HtmlTagVoid(String::new()),
457468
TokenType::ScriptTagOpen(String::new()),
469+
TokenType::ScriptTagClose(String::new()), // Added
458470
TokenType::StyleTagOpen(String::new()),
471+
TokenType::StyleTagClose(String::new()), // Added
459472
TokenType::Newline,
460473
TokenType::Eof,
461474
];
462475

476+
let mut nesting = 0;
463477
while !self.is_at_end() {
464-
if SYNC_TYPES.contains(self.peek()?.token_type()) {
465-
return Ok(());
478+
let token = self.peek()?;
479+
match token.token_type() {
480+
TokenType::HtmlTagOpen(_)
481+
| TokenType::ScriptTagOpen(_)
482+
| TokenType::StyleTagOpen(_) => {
483+
nesting += 1;
484+
}
485+
TokenType::HtmlTagClose(_)
486+
| TokenType::ScriptTagClose(_)
487+
| TokenType::StyleTagClose(_) => {
488+
nesting -= 1;
489+
if nesting < 0 {
490+
return Ok(());
491+
}
492+
}
493+
_ if SYNC_TYPES.contains(token.token_type()) && nesting == 0 => {
494+
return Ok(());
495+
}
496+
_ => {}
466497
}
467498
self.consume()?;
468499
}
@@ -609,7 +640,7 @@ mod tests {
609640
}
610641

611642
// hangs for some reason
612-
// #[test]
643+
#[test]
613644
fn test_parse_full() {
614645
let source = r#"<!DOCTYPE html>
615646
<html>
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
source: crates/djls-ast/src/parser.rs
3+
expression: ast
4+
---
5+
nodes:
6+
- Html:
7+
Doctype: "!DOCTYPE"
8+
- Html:
9+
Element:
10+
tag_name: html
11+
attributes: {}
12+
children:
13+
- Html:
14+
Element:
15+
tag_name: head
16+
attributes: {}
17+
children:
18+
- Style:
19+
Element:
20+
attributes:
21+
type:
22+
Value: text/css
23+
children:
24+
- Style:
25+
Comment: Style header
26+
- Text: ".header "
27+
- Text: "{"
28+
- Text: "color: blue; }"
29+
- Script:
30+
Element:
31+
attributes:
32+
script: Boolean
33+
type:
34+
Value: text/javascript
35+
children:
36+
- Script:
37+
Comment:
38+
content: Init app
39+
kind: SingleLine
40+
- Text: "const app = "
41+
- Text: "{"
42+
- Script:
43+
Comment:
44+
content: Config
45+
kind: MultiLine
46+
- Text: "debug: true"
47+
- Text: "};"
48+
- Html:
49+
Element:
50+
tag_name: body
51+
attributes: {}
52+
children:
53+
- Html:
54+
Comment: Header section
55+
- Html:
56+
Element:
57+
tag_name: div
58+
attributes:
59+
class:
60+
Value: header
61+
data-value:
62+
Value: "123"
63+
disabled: Boolean
64+
id:
65+
Value: main
66+
children:
67+
- Django:
68+
Tag:
69+
kind: If
70+
bits:
71+
- if
72+
- user.is_authenticated
73+
children:
74+
- Django:
75+
Comment: Welcome message
76+
- Html:
77+
Element:
78+
tag_name: h1
79+
attributes: {}
80+
children:
81+
- Text: "Welcome, "
82+
- Django:
83+
Variable:
84+
bits:
85+
- user
86+
- name
87+
filters:
88+
- name: default
89+
arguments:
90+
- Guest
91+
- name: title
92+
arguments: []
93+
- Text: "!"
94+
- Django:
95+
Tag:
96+
kind: If
97+
bits:
98+
- if
99+
- user.is_staff
100+
children:
101+
- Html:
102+
Element:
103+
tag_name: span
104+
attributes: {}
105+
children:
106+
- Text: Admin

0 commit comments

Comments
 (0)