mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-27 20:42:14 +00:00
fix parseing of django tags with potential intermediates
This commit is contained in:
parent
a5e42fe7a4
commit
134f3fea54
2 changed files with 141 additions and 4 deletions
|
@ -155,8 +155,18 @@ impl Parser {
|
||||||
if tag == end_tag {
|
if tag == end_tag {
|
||||||
self.consume()?;
|
self.consume()?;
|
||||||
break;
|
break;
|
||||||
|
} else if !tag.starts_with("end") {
|
||||||
|
// For intermediate tags (else, elif, empty, etc.)
|
||||||
|
self.consume()?;
|
||||||
|
// Create a new Tag node for the intermediate tag
|
||||||
|
children.push(Node::Django(DjangoNode::Tag {
|
||||||
|
kind: DjangoTagKind::from_str(&tag)?,
|
||||||
|
bits: vec![tag.clone()],
|
||||||
|
children: Vec::new(),
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return Err(ParserError::ErrorSignal(Signal::ClosingTagFound(tag)));
|
||||||
}
|
}
|
||||||
// If it's not our end tag, keep collecting children
|
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
|
@ -453,16 +463,37 @@ impl Parser {
|
||||||
const SYNC_TYPES: &[TokenType] = &[
|
const SYNC_TYPES: &[TokenType] = &[
|
||||||
TokenType::DjangoBlock(String::new()),
|
TokenType::DjangoBlock(String::new()),
|
||||||
TokenType::HtmlTagOpen(String::new()),
|
TokenType::HtmlTagOpen(String::new()),
|
||||||
|
TokenType::HtmlTagClose(String::new()), // Added
|
||||||
TokenType::HtmlTagVoid(String::new()),
|
TokenType::HtmlTagVoid(String::new()),
|
||||||
TokenType::ScriptTagOpen(String::new()),
|
TokenType::ScriptTagOpen(String::new()),
|
||||||
|
TokenType::ScriptTagClose(String::new()), // Added
|
||||||
TokenType::StyleTagOpen(String::new()),
|
TokenType::StyleTagOpen(String::new()),
|
||||||
|
TokenType::StyleTagClose(String::new()), // Added
|
||||||
TokenType::Newline,
|
TokenType::Newline,
|
||||||
TokenType::Eof,
|
TokenType::Eof,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let mut nesting = 0;
|
||||||
while !self.is_at_end() {
|
while !self.is_at_end() {
|
||||||
if SYNC_TYPES.contains(self.peek()?.token_type()) {
|
let token = self.peek()?;
|
||||||
return Ok(());
|
match token.token_type() {
|
||||||
|
TokenType::HtmlTagOpen(_)
|
||||||
|
| TokenType::ScriptTagOpen(_)
|
||||||
|
| TokenType::StyleTagOpen(_) => {
|
||||||
|
nesting += 1;
|
||||||
|
}
|
||||||
|
TokenType::HtmlTagClose(_)
|
||||||
|
| TokenType::ScriptTagClose(_)
|
||||||
|
| TokenType::StyleTagClose(_) => {
|
||||||
|
nesting -= 1;
|
||||||
|
if nesting < 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ if SYNC_TYPES.contains(token.token_type()) && nesting == 0 => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
self.consume()?;
|
self.consume()?;
|
||||||
}
|
}
|
||||||
|
@ -609,7 +640,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
// hangs for some reason
|
// hangs for some reason
|
||||||
// #[test]
|
#[test]
|
||||||
fn test_parse_full() {
|
fn test_parse_full() {
|
||||||
let source = r#"<!DOCTYPE html>
|
let source = r#"<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
---
|
||||||
|
source: crates/djls-ast/src/parser.rs
|
||||||
|
expression: ast
|
||||||
|
---
|
||||||
|
nodes:
|
||||||
|
- Html:
|
||||||
|
Doctype: "!DOCTYPE"
|
||||||
|
- Html:
|
||||||
|
Element:
|
||||||
|
tag_name: html
|
||||||
|
attributes: {}
|
||||||
|
children:
|
||||||
|
- Html:
|
||||||
|
Element:
|
||||||
|
tag_name: head
|
||||||
|
attributes: {}
|
||||||
|
children:
|
||||||
|
- Style:
|
||||||
|
Element:
|
||||||
|
attributes:
|
||||||
|
type:
|
||||||
|
Value: text/css
|
||||||
|
children:
|
||||||
|
- Style:
|
||||||
|
Comment: Style header
|
||||||
|
- Text: ".header "
|
||||||
|
- Text: "{"
|
||||||
|
- Text: "color: blue; }"
|
||||||
|
- Script:
|
||||||
|
Element:
|
||||||
|
attributes:
|
||||||
|
script: Boolean
|
||||||
|
type:
|
||||||
|
Value: text/javascript
|
||||||
|
children:
|
||||||
|
- Script:
|
||||||
|
Comment:
|
||||||
|
content: Init app
|
||||||
|
kind: SingleLine
|
||||||
|
- Text: "const app = "
|
||||||
|
- Text: "{"
|
||||||
|
- Script:
|
||||||
|
Comment:
|
||||||
|
content: Config
|
||||||
|
kind: MultiLine
|
||||||
|
- Text: "debug: true"
|
||||||
|
- Text: "};"
|
||||||
|
- Html:
|
||||||
|
Element:
|
||||||
|
tag_name: body
|
||||||
|
attributes: {}
|
||||||
|
children:
|
||||||
|
- Html:
|
||||||
|
Comment: Header section
|
||||||
|
- Html:
|
||||||
|
Element:
|
||||||
|
tag_name: div
|
||||||
|
attributes:
|
||||||
|
class:
|
||||||
|
Value: header
|
||||||
|
data-value:
|
||||||
|
Value: "123"
|
||||||
|
disabled: Boolean
|
||||||
|
id:
|
||||||
|
Value: main
|
||||||
|
children:
|
||||||
|
- Django:
|
||||||
|
Tag:
|
||||||
|
kind: If
|
||||||
|
bits:
|
||||||
|
- if
|
||||||
|
- user.is_authenticated
|
||||||
|
children:
|
||||||
|
- Django:
|
||||||
|
Comment: Welcome message
|
||||||
|
- Html:
|
||||||
|
Element:
|
||||||
|
tag_name: h1
|
||||||
|
attributes: {}
|
||||||
|
children:
|
||||||
|
- Text: "Welcome, "
|
||||||
|
- Django:
|
||||||
|
Variable:
|
||||||
|
bits:
|
||||||
|
- user
|
||||||
|
- name
|
||||||
|
filters:
|
||||||
|
- name: default
|
||||||
|
arguments:
|
||||||
|
- Guest
|
||||||
|
- name: title
|
||||||
|
arguments: []
|
||||||
|
- Text: "!"
|
||||||
|
- Django:
|
||||||
|
Tag:
|
||||||
|
kind: If
|
||||||
|
bits:
|
||||||
|
- if
|
||||||
|
- user.is_staff
|
||||||
|
children:
|
||||||
|
- Html:
|
||||||
|
Element:
|
||||||
|
tag_name: span
|
||||||
|
attributes: {}
|
||||||
|
children:
|
||||||
|
- Text: Admin
|
Loading…
Add table
Add a link
Reference in a new issue