This commit is contained in:
Josh Thomas 2025-01-05 01:38:30 -06:00
parent a99ec2d86f
commit b3f80eaeb3
43 changed files with 1220 additions and 75 deletions

View file

@ -42,7 +42,7 @@ impl Ast {
}
#[derive(Clone, Default, Debug, Serialize)]
pub struct LineOffsets(Vec<u32>);
pub struct LineOffsets(pub Vec<u32>);
impl LineOffsets {
pub fn new() -> Self {
@ -55,11 +55,33 @@ impl LineOffsets {
}
pub fn position_to_line_col(&self, offset: u32) -> (u32, u32) {
eprintln!("LineOffsets: Converting position {} to line/col. Offsets: {:?}", offset, self.0);
// Find which line contains this offset by looking for the first line start
// that's greater than our position
let line = match self.0.binary_search(&offset) {
Ok(line) => line,
Err(line) => if line > 0 { line - 1 } else { line },
Ok(exact_line) => exact_line, // We're exactly at a line start, so we're on that line
Err(next_line) => {
if next_line == 0 {
0 // Before first line start, so we're on line 0
} else {
let prev_line = next_line - 1;
// If we're at the start of the next line, we're on that line
if offset == self.0[next_line] - 1 {
prev_line
} else {
// Otherwise we're on the previous line
prev_line
}
}
}
};
// Calculate column as offset from line start
let col = offset - self.0[line];
eprintln!("LineOffsets: Found line {} starting at offset {}", line, self.0[line]);
eprintln!("LineOffsets: Calculated col {} as {} - {}", col, offset, self.0[line]);
(line as u32, col)
}
@ -185,6 +207,7 @@ mod tests {
fn test_variable_spans() {
let template = "Hello\n{{ user.name }}\nWorld";
let tokens = Lexer::new(template).tokenize().unwrap();
println!("Tokens: {:#?}", tokens); // Add debug print
let mut parser = Parser::new(tokens);
let ast = parser.parse().unwrap();
@ -236,6 +259,8 @@ mod tests {
// Check content span
if let Some(content) = children {
if let Node::Text { span, .. } = &content[0] {
eprintln!("content {:?}", content);
eprintln!("span start {:?}", span.start());
let (content_line, content_col) =
ast.line_offsets.position_to_line_col(*span.start());
assert_eq!(

View file

@ -60,8 +60,11 @@ impl Lexer {
},
'\n' => {
self.consume()?;
let token = TokenType::Newline;
eprintln!("Lexer: Found newline at position {}, incrementing line from {} to {}",
self.start, self.line, self.line + 1);
self.line += 1;
TokenType::Newline
token
}
' ' | '\t' | '\r' => {
let mut count = 1;

View file

@ -15,21 +15,25 @@ impl Parser {
pub fn parse(&mut self) -> Result<Ast, ParserError> {
let mut ast = Ast::default();
let mut line_offsets = LineOffsets::new();
let mut line_offsets = LineOffsets::new(); // Already contains [0]
// First pass: collect line offsets
let mut current_offset = 0;
for token in self.tokens.tokens() {
match token.token_type() {
TokenType::Newline => {
current_offset += 1; // Add 1 for the newline character
line_offsets.add_line(current_offset as u32);
}
_ => {
if let Some(len) = token.token_type().len() {
current_offset += len;
if let Some(start) = token.start() {
eprintln!("Parser: Found newline at position {}", start);
// Add line offset at the start of the next line
line_offsets.add_line(*start as u32 + 1);
eprintln!("Parser: Added line offset {} at position {}", line_offsets.0.len(), start + 1);
}
}
TokenType::Whitespace(count) => {
if let Some(start) = token.start() {
eprintln!("Parser: Found whitespace of length {} at position {}", count, start);
}
}
_ => {}
}
}
@ -189,20 +193,21 @@ impl Parser {
}
let closing_token = self.peek_previous()?;
let closing_content = match closing_token.token_type() {
TokenType::DjangoBlock(content) => content.len(),
TokenType::DjangoBlock(content) => content.len() + 5, // Add 5 for {% and %}
_ => 0,
};
total_length = (closing_token.start().unwrap_or(0) + closing_content)
- start_pos as usize;
let closing_start = closing_token.start().unwrap_or(0);
total_length = (closing_start + closing_content) - start_pos as usize;
let closing_span = Span::new(
closing_start as u32,
closing_content as u16,
);
children.push(Node::Block {
block_type: BlockType::Closing,
name: tag,
bits: vec![],
children: None,
span: Span::new(
closing_token.start().unwrap_or(0) as u32,
closing_content as u16,
),
span: closing_span,
tag_span,
});
found_closing_tag = true;
@ -210,7 +215,7 @@ impl Parser {
}
// Check if intermediate tag
if let Some(branches) = &spec.branches {
if let Some(branch) = branches.iter().find(|i| i.name == tag) {
if let Some(branch) = branches.iter().find(|b| b.name == tag) {
// If we have a current branch, add it to children
if let Some((name, bits, branch_children)) = current_branch {
let branch_span = Span::new(start_pos, total_length as u16);
@ -281,10 +286,11 @@ impl Parser {
}
fn parse_django_variable(&mut self, s: &str) -> Result<Node, ParserError> {
let start_token = self.peek_previous()?;
let start_pos = start_token.start().unwrap_or(0) as u32;
let token = self.peek_previous()?;
let start_pos = token.start().unwrap_or(0) as u32;
let s = s.trim(); // Trim whitespace
let length = s.len() as u16;
let span = Span::new(start_pos, length);
let span = Span::new(start_pos + 3, length); // Add 3 to skip "{{ "
let parts: Vec<&str> = s.split('|').collect();
let bits: Vec<String> = parts[0].trim().split('.').map(String::from).collect();
@ -324,10 +330,30 @@ impl Parser {
}
fn parse_text(&mut self) -> Result<Node, ParserError> {
let start_token = self.peek()?;
let start_pos = start_token.start().unwrap_or(0) as u32;
let mut start_pos = self.peek()?.start().unwrap_or(0) as u32;
let mut text = String::new();
// Skip any leading newlines and whitespace
while let Ok(token) = self.peek() {
match token.token_type() {
TokenType::Newline => {
self.consume()?;
text.push('\n');
if let Ok(next) = self.peek() {
start_pos = next.start().unwrap_or(0) as u32;
}
}
TokenType::Whitespace(len) => {
self.consume()?;
text.push_str(&" ".repeat(*len));
if let Ok(next) = self.peek() {
start_pos = next.start().unwrap_or(0) as u32;
}
}
_ => break,
}
}
while let Ok(token) = self.peek() {
match token.token_type() {
TokenType::DjangoBlock(_)
@ -530,7 +556,8 @@ mod tests {
}
#[test]
fn test_parse_complex_if_elif() {
let source = "{% if x > 0 %}Positive{% elif x < 0 %}Negative{% else %}Zero{% endif %}";
let source =
"{% if x > 0 %}Positive{% elif x < 0 %}Negative{% else %}Zero{% endif %}";
let tokens = Lexer::new(source).tokenize().unwrap();
let mut parser = Parser::new(tokens);
let ast = parser.parse().unwrap();
@ -734,6 +761,7 @@ mod tests {
let ast = parser.parse().unwrap();
let offsets = ast.line_offsets();
eprintln!("{:?}", offsets);
assert_eq!(offsets.position_to_line_col(0), (0, 0)); // Start of line 1
assert_eq!(offsets.position_to_line_col(6), (1, 0)); // Start of line 2
}

View file

@ -15,4 +15,5 @@ nodes:
length: 18
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,20 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 608
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<!-- HTML comment -->"
span:
start: 0
length: 21
- Comment:
content: Django comment
span:
start: 21
length: 18
line_offsets:
- 0
errors: []

View file

@ -71,4 +71,5 @@ nodes:
length: 8
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,76 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 535
expression: ast
snapshot_kind: text
---
nodes:
- Block:
block_type: Standard
name: if
bits:
- if
- x
- ">"
- "0"
children:
- Text:
content: Positive
span:
start: 14
length: 8
- Block:
block_type: Branch
name: elif
bits:
- x
- "<"
- "0"
children:
- Text:
content: Negative
span:
start: 38
length: 8
span:
start: 0
length: 8
tag_span:
start: 0
length: 8
- Block:
block_type: Branch
name: else
bits: []
children:
- Text:
content: Zero
span:
start: 56
length: 4
span:
start: 0
length: 8
tag_span:
start: 0
length: 8
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 60
length: 5
tag_span:
start: 0
length: 8
span:
start: 0
length: 65
tag_span:
start: 0
length: 8
line_offsets:
- 0
errors: []

View file

@ -17,7 +17,7 @@ nodes:
- item
filters: []
span:
start: 23
start: 25
length: 4
- Block:
block_type: Branch
@ -54,4 +54,5 @@ nodes:
length: 17
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,59 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 527
expression: ast
snapshot_kind: text
---
nodes:
- Block:
block_type: Standard
name: for
bits:
- for
- item
- in
- items
children:
- Variable:
bits:
- item
filters: []
span:
start: 26
length: 4
- Block:
block_type: Branch
name: empty
bits: []
children:
- Text:
content: No items
span:
start: 44
length: 8
span:
start: 0
length: 17
tag_span:
start: 0
length: 17
- Block:
block_type: Closing
name: endfor
bits: []
children: ~
span:
start: 52
length: 6
tag_span:
start: 0
length: 17
span:
start: 0
length: 58
tag_span:
start: 0
length: 17
line_offsets:
- 0
errors: []

View file

@ -34,4 +34,5 @@ nodes:
length: 24
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,39 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 519
expression: ast
snapshot_kind: text
---
nodes:
- Block:
block_type: Standard
name: if
bits:
- if
- user.is_authenticated
children:
- Text:
content: Welcome
span:
start: 30
length: 7
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 37
length: 5
tag_span:
start: 0
length: 24
span:
start: 0
length: 42
tag_span:
start: 0
length: 24
line_offsets:
- 0
errors: []

View file

@ -11,11 +11,12 @@ nodes:
- name: title
arguments: []
span:
start: 10
start: 12
length: 5
span:
start: 0
start: 2
length: 15
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,23 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 503
expression: ast
snapshot_kind: text
---
nodes:
- Variable:
bits:
- user
- name
filters:
- name: title
arguments: []
span:
start: 10
length: 5
span:
start: 3
length: 15
line_offsets:
- 0
errors: []

View file

@ -11,21 +11,22 @@ nodes:
arguments:
- "'nothing'"
span:
start: 6
start: 8
length: 17
- name: title
arguments: []
span:
start: 24
start: 26
length: 5
- name: upper
arguments: []
span:
start: 30
start: 32
length: 5
span:
start: 0
start: 2
length: 35
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,33 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 511
expression: ast
snapshot_kind: text
---
nodes:
- Variable:
bits:
- value
filters:
- name: default
arguments:
- "'nothing'"
span:
start: 6
length: 17
- name: title
arguments: []
span:
start: 24
length: 5
- name: upper
arguments: []
span:
start: 30
length: 5
span:
start: 3
length: 35
line_offsets:
- 0
errors: []

View file

@ -28,16 +28,16 @@ nodes:
- name: title
arguments: []
span:
start: 54
start: 56
length: 5
- name: default
arguments:
- "'Guest'"
span:
start: 60
start: 62
length: 15
span:
start: 44
start: 46
length: 31
- Text:
content: "\n "
@ -98,7 +98,7 @@ nodes:
- name
filters: []
span:
start: 168
start: 170
length: 10
- Text:
content: "\n "
@ -252,16 +252,17 @@ nodes:
length: 1
line_offsets:
- 0
- 34
- 70
- 99
- 130
- 149
- 184
- 214
- 224
- 244
- 255
- 260
- 270
- 0
- 40
- 82
- 117
- 160
- 185
- 232
- 274
- 290
- 310
- 327
- 338
- 348
errors: []

View file

@ -0,0 +1,269 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 564
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "Welcome, "
span:
start: 0
length: 9
- Block:
block_type: Standard
name: if
bits:
- if
- user.is_authenticated
children:
- Text:
content: "\n "
span:
start: 39
length: 5
- Variable:
bits:
- user
- name
filters:
- name: title
arguments: []
span:
start: 54
length: 5
- name: default
arguments:
- "'Guest'"
span:
start: 60
length: 15
span:
start: 47
length: 31
- Text:
content: "\n "
span:
start: 81
length: 5
- Block:
block_type: Standard
name: for
bits:
- for
- group
- in
- user.groups
children:
- Text:
content: "\n "
span:
start: 116
length: 9
- Block:
block_type: Standard
name: if
bits:
- if
- forloop.first
children:
- Text:
content: (
span:
start: 147
length: 1
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 148
length: 5
tag_span:
start: 125
length: 16
span:
start: 125
length: 28
tag_span:
start: 125
length: 16
- Text:
content: "\n "
span:
start: 159
length: 9
- Variable:
bits:
- group
- name
filters: []
span:
start: 171
length: 10
- Text:
content: "\n "
span:
start: 184
length: 9
- Block:
block_type: Standard
name: if
bits:
- if
- not
- forloop.last
children:
- Text:
content: ", "
span:
start: 218
length: 2
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 220
length: 5
tag_span:
start: 193
length: 19
span:
start: 193
length: 32
tag_span:
start: 193
length: 19
- Text:
content: "\n "
span:
start: 231
length: 9
- Block:
block_type: Standard
name: if
bits:
- if
- forloop.last
children:
- Text:
content: )
span:
start: 261
length: 1
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 262
length: 5
tag_span:
start: 240
length: 15
span:
start: 240
length: 27
tag_span:
start: 240
length: 15
- Text:
content: "\n "
span:
start: 273
length: 5
- Block:
block_type: Branch
name: empty
bits: []
children:
- Text:
content: "\n (no groups)\n "
span:
start: 289
length: 25
span:
start: 86
length: 24
tag_span:
start: 86
length: 24
- Block:
block_type: Closing
name: endfor
bits: []
children: ~
span:
start: 314
length: 6
tag_span:
start: 86
length: 24
span:
start: 86
length: 234
tag_span:
start: 86
length: 24
- Text:
content: "\n"
span:
start: 326
length: 1
- Block:
block_type: Branch
name: else
bits: []
children:
- Text:
content: "\n Guest\n"
span:
start: 337
length: 11
span:
start: 9
length: 24
tag_span:
start: 9
length: 24
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 348
length: 5
tag_span:
start: 9
length: 24
span:
start: 9
length: 344
tag_span:
start: 9
length: 24
- Text:
content: "!"
span:
start: 359
length: 1
line_offsets:
- 0
- 40
- 82
- 117
- 160
- 185
- 232
- 274
- 290
- 310
- 327
- 338
- 348
errors: []

View file

@ -25,7 +25,7 @@ nodes:
- name
filters: []
span:
start: 43
start: 45
length: 9
- Block:
block_type: Closing
@ -63,4 +63,5 @@ nodes:
length: 17
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,68 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 544
expression: ast
snapshot_kind: text
---
nodes:
- Block:
block_type: Standard
name: for
bits:
- for
- item
- in
- items
children:
- Block:
block_type: Standard
name: if
bits:
- if
- item.active
children:
- Variable:
bits:
- item
- name
filters: []
span:
start: 46
length: 9
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 58
length: 5
tag_span:
start: 23
length: 14
span:
start: 23
length: 40
tag_span:
start: 23
length: 14
- Block:
block_type: Closing
name: endfor
bits: []
children: ~
span:
start: 69
length: 6
tag_span:
start: 0
length: 17
span:
start: 0
length: 75
tag_span:
start: 0
length: 17
line_offsets:
- 0
errors: []

View file

@ -36,7 +36,7 @@ nodes:
- name
filters: []
span:
start: 150
start: 152
length: 9
- Text:
content: "</p>\n <div>\n "
@ -72,7 +72,7 @@ nodes:
- item
filters: []
span:
start: 294
start: 296
length: 4
- Text:
content: "</span>\n "
@ -108,17 +108,18 @@ nodes:
start: 48
length: 24
line_offsets:
- 0
- 0
- 24
- 44
- 73
- 123
- 156
- 79
- 131
- 170
- 228
- 254
- 284
- 299
- 332
- 184
- 244
- 276
- 312
- 333
- 366
errors:
- UnclosedTag: if

View file

@ -0,0 +1,126 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 677
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<div class=\"container\">\n <h1>Header</h1>\n "
span:
start: 0
length: 48
- Block:
block_type: Standard
name: if
bits:
- if
- user.is_authenticated
children:
- Text:
content: "\n "
span:
start: 78
length: 9
- Comment:
content: This if is unclosed which does matter
span:
start: 87
length: 41
- Text:
content: "\n <p>Welcome "
span:
start: 130
length: 20
- Variable:
bits:
- user
- name
filters: []
span:
start: 153
length: 9
- Text:
content: "</p>\n <div>\n "
span:
start: 165
length: 31
- Comment:
content: "This div is unclosed which doesn't matter"
span:
start: 196
length: 45
- Text:
content: "\n "
span:
start: 243
length: 9
- Block:
block_type: Standard
name: for
bits:
- for
- item
- in
- items
children:
- Text:
content: "\n <span>"
span:
start: 275
length: 19
- Variable:
bits:
- item
filters: []
span:
start: 297
length: 4
- Text:
content: "</span>\n "
span:
start: 304
length: 16
- Block:
block_type: Closing
name: endfor
bits: []
children: ~
span:
start: 320
length: 6
tag_span:
start: 252
length: 17
span:
start: 252
length: 74
tag_span:
start: 252
length: 17
- Text:
content: "\n <footer>Page Footer</footer>\n</div>"
span:
start: 332
length: 40
span:
start: 48
length: 24
tag_span:
start: 48
length: 24
line_offsets:
- 0
- 24
- 44
- 79
- 131
- 170
- 184
- 244
- 276
- 312
- 333
- 366
errors:
- UnclosedTag: if

View file

@ -18,7 +18,7 @@ nodes:
- name
filters: []
span:
start: 23
start: 25
length: 9
span:
start: 0
@ -28,5 +28,6 @@ nodes:
length: 17
line_offsets:
- 0
- 0
errors:
- UnclosedTag: for

View file

@ -0,0 +1,34 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 638
expression: ast
snapshot_kind: text
---
nodes:
- Block:
block_type: Standard
name: for
bits:
- for
- item
- in
- items
children:
- Variable:
bits:
- item
- name
filters: []
span:
start: 26
length: 9
span:
start: 0
length: 17
tag_span:
start: 0
length: 17
line_offsets:
- 0
errors:
- UnclosedTag: for

View file

@ -23,5 +23,6 @@ nodes:
length: 24
line_offsets:
- 0
- 0
errors:
- UnclosedTag: if

View file

@ -0,0 +1,29 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 628
expression: ast
snapshot_kind: text
---
nodes:
- Block:
block_type: Standard
name: if
bits:
- if
- user.is_authenticated
children:
- Text:
content: Welcome
span:
start: 30
length: 7
span:
start: 0
length: 24
tag_span:
start: 0
length: 24
line_offsets:
- 0
errors:
- UnclosedTag: if

View file

@ -10,4 +10,5 @@ nodes:
length: 5
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,15 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 619
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<div>"
span:
start: 0
length: 5
line_offsets:
- 0
errors: []

View file

@ -10,4 +10,5 @@ nodes:
length: 28
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,15 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 648
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<script>console.log('test');"
span:
start: 0
length: 28
line_offsets:
- 0
errors: []

View file

@ -10,4 +10,5 @@ nodes:
length: 27
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,15 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 657
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<style>body { color: blue; "
span:
start: 0
length: 27
line_offsets:
- 0
errors: []

View file

@ -38,16 +38,16 @@ nodes:
- name: title
arguments: []
span:
start: 571
start: 573
length: 5
- name: default
arguments:
- "'Guest'"
span:
start: 577
start: 579
length: 15
span:
start: 561
start: 563
length: 31
- Text:
content: "!</h1>\n "
@ -127,6 +127,7 @@ nodes:
start: 799
length: 35
line_offsets:
- 0
- 0
- 16
- 23
@ -146,15 +147,15 @@ line_offsets:
- 354
- 386
- 451
- 488
- 524
- 591
- 624
- 663
- 684
- 722
- 744
- 762
- 777
- 789
- 494
- 532
- 605
- 644
- 683
- 710
- 748
- 776
- 800
- 815
- 827
errors: []

View file

@ -0,0 +1,162 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 720
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<!DOCTYPE html>\n<html>\n <head>\n <style type=\"text/css\">\n /* Style header */\n .header { color: blue; }\n </style>\n <script type=\"text/javascript\">\n // Init app\n const app = {\n /* Config */\n debug: true\n };\n </script>\n </head>\n <body>\n <!-- Header section -->\n <div class=\"header\" id=\"main\" data-value=\"123\" disabled>\n "
span:
start: 0
length: 463
- Block:
block_type: Standard
name: if
bits:
- if
- user.is_authenticated
children:
- Text:
content: "\n "
span:
start: 493
length: 17
- Comment:
content: Welcome message
span:
start: 510
length: 19
- Text:
content: "\n <h1>Welcome, "
span:
start: 531
length: 30
- Variable:
bits:
- user
- name
filters:
- name: title
arguments: []
span:
start: 571
length: 5
- name: default
arguments:
- "'Guest'"
span:
start: 577
length: 15
span:
start: 564
length: 31
- Text:
content: "!</h1>\n "
span:
start: 598
length: 23
- Block:
block_type: Standard
name: if
bits:
- if
- user.is_staff
children:
- Text:
content: "\n <span>Admin</span>\n "
span:
start: 643
length: 56
- Block:
block_type: Branch
name: else
bits: []
children:
- Text:
content: "\n <span>User</span>\n "
span:
start: 709
length: 55
span:
start: 621
length: 16
tag_span:
start: 621
length: 16
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 764
length: 5
tag_span:
start: 621
length: 16
span:
start: 621
length: 148
tag_span:
start: 621
length: 16
- Text:
content: "\n "
span:
start: 775
length: 13
- Block:
block_type: Closing
name: endif
bits: []
children: ~
span:
start: 788
length: 5
tag_span:
start: 463
length: 24
span:
start: 463
length: 330
tag_span:
start: 463
length: 24
- Text:
content: "\n </div>\n </body>\n</html>"
span:
start: 799
length: 35
line_offsets:
- 0
- 16
- 23
- 34
- 66
- 97
- 134
- 151
- 191
- 215
- 241
- 270
- 298
- 313
- 331
- 343
- 354
- 386
- 451
- 494
- 532
- 605
- 644
- 683
- 710
- 748
- 776
- 800
- 815
- 827
errors: []

View file

@ -10,4 +10,5 @@ nodes:
length: 15
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,15 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 476
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<!DOCTYPE html>"
span:
start: 0
length: 15
line_offsets:
- 0
errors: []

View file

@ -10,4 +10,5 @@ nodes:
length: 34
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,15 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 484
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<div class=\"container\">Hello</div>"
span:
start: 0
length: 34
line_offsets:
- 0
errors: []

View file

@ -10,4 +10,5 @@ nodes:
length: 21
line_offsets:
- 0
- 0
errors: []

View file

@ -0,0 +1,15 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 492
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<input type=\"text\" />"
span:
start: 0
length: 21
line_offsets:
- 0
errors: []

View file

@ -9,6 +9,7 @@ nodes:
start: 0
length: 142
line_offsets:
- 0
- 0
- 32
- 59

View file

@ -0,0 +1,21 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 581
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<script type=\"text/javascript\">\n // Single line comment\n const x = 1;\n /* Multi-line\n comment */\n console.log(x);\n</script>"
span:
start: 0
length: 142
line_offsets:
- 0
- 32
- 59
- 76
- 94
- 113
- 133
errors: []

View file

@ -9,6 +9,7 @@ nodes:
start: 0
length: 97
line_offsets:
- 0
- 0
- 24
- 48

View file

@ -0,0 +1,20 @@
---
source: crates/djls-template-ast/src/parser.rs
assertion_line: 597
expression: ast
snapshot_kind: text
---
nodes:
- Text:
content: "<style type=\"text/css\">\n /* Header styles */\n .header {\n color: blue;\n }\n</style>"
span:
start: 0
length: 97
line_offsets:
- 0
- 24
- 48
- 62
- 83
- 89
errors: []