mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-13 05:46:17 +00:00
wip
This commit is contained in:
parent
00eca98c6a
commit
f1cc33f173
21 changed files with 1323 additions and 651 deletions
|
@ -5,7 +5,6 @@ use thiserror::Error;
|
|||
pub struct Ast {
|
||||
nodes: Vec<Node>,
|
||||
line_offsets: LineOffsets,
|
||||
errors: Vec<AstError>,
|
||||
}
|
||||
|
||||
impl Ast {
|
||||
|
@ -17,10 +16,6 @@ impl Ast {
|
|||
&self.line_offsets
|
||||
}
|
||||
|
||||
pub fn errors(&self) -> &Vec<AstError> {
|
||||
&self.errors
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, node: Node) {
|
||||
self.nodes.push(node);
|
||||
}
|
||||
|
@ -29,12 +24,8 @@ impl Ast {
|
|||
self.line_offsets = line_offsets
|
||||
}
|
||||
|
||||
pub fn add_error(&mut self, error: AstError) {
|
||||
self.errors.push(error);
|
||||
}
|
||||
|
||||
pub fn finalize(&mut self) -> Result<Ast, AstError> {
|
||||
if self.nodes.is_empty() && self.errors.is_empty() {
|
||||
if self.nodes.is_empty() {
|
||||
return Err(AstError::EmptyAst);
|
||||
}
|
||||
Ok(self.clone())
|
||||
|
@ -55,15 +46,13 @@ 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(exact_line) => exact_line, // We're exactly at a line start, so we're on that 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
|
||||
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
|
||||
|
@ -79,9 +68,6 @@ impl LineOffsets {
|
|||
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
@ -93,11 +79,11 @@ impl LineOffsets {
|
|||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct Span {
|
||||
start: u32,
|
||||
length: u16,
|
||||
length: u32,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn new(start: u32, length: u16) -> Self {
|
||||
pub fn new(start: u32, length: u32) -> Self {
|
||||
Self { start, length }
|
||||
}
|
||||
|
||||
|
@ -105,28 +91,21 @@ impl Span {
|
|||
&self.start
|
||||
}
|
||||
|
||||
pub fn length(&self) -> &u16 {
|
||||
pub fn length(&self) -> &u32 {
|
||||
&self.length
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum Node {
|
||||
Text {
|
||||
content: String,
|
||||
span: Span,
|
||||
},
|
||||
Block(Block),
|
||||
Comment {
|
||||
content: String,
|
||||
span: Span,
|
||||
},
|
||||
Block {
|
||||
block_type: BlockType,
|
||||
name: String,
|
||||
bits: Vec<String>,
|
||||
children: Option<Vec<Node>>,
|
||||
Text {
|
||||
content: String,
|
||||
span: Span,
|
||||
tag_span: Span,
|
||||
},
|
||||
Variable {
|
||||
bits: Vec<String>,
|
||||
|
@ -136,10 +115,45 @@ pub enum Node {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum BlockType {
|
||||
Standard,
|
||||
Branch,
|
||||
Closing,
|
||||
pub enum Block {
|
||||
Block {
|
||||
tag: Tag,
|
||||
nodes: Vec<Node>,
|
||||
closing: Option<Box<Block>>,
|
||||
assignments: Option<Vec<Assignment>>,
|
||||
},
|
||||
Branch {
|
||||
tag: Tag,
|
||||
nodes: Vec<Node>,
|
||||
},
|
||||
Tag {
|
||||
tag: Tag,
|
||||
},
|
||||
Inclusion {
|
||||
tag: Tag,
|
||||
template_name: String,
|
||||
},
|
||||
Variable {
|
||||
tag: Tag,
|
||||
},
|
||||
Closing {
|
||||
tag: Tag,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct Tag {
|
||||
pub name: String,
|
||||
pub bits: Vec<String>,
|
||||
pub span: Span,
|
||||
pub tag_span: Span,
|
||||
pub assignment: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct Assignment {
|
||||
pub target: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
|
@ -271,8 +285,8 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
// Full block span should cover entire template
|
||||
assert_eq!(*span.length() as u32, 42);
|
||||
// Full block span should cover only the opening tag
|
||||
assert_eq!(*span.length() as u32, 14);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,48 +306,43 @@ mod tests {
|
|||
let ast = parser.parse().unwrap();
|
||||
|
||||
// Test nested block positions
|
||||
let (outer_if, inner_if) = {
|
||||
let nodes = ast.nodes();
|
||||
let outer = nodes
|
||||
let nodes = ast.nodes();
|
||||
let outer_if = nodes
|
||||
.iter()
|
||||
.find(|n| matches!(n, Node::Block { .. }))
|
||||
.unwrap();
|
||||
|
||||
if let Node::Block {
|
||||
span: outer_span,
|
||||
children: Some(children),
|
||||
..
|
||||
} = outer_if
|
||||
{
|
||||
// Find the inner if block in the children
|
||||
let inner_if = children
|
||||
.iter()
|
||||
.find(|n| matches!(n, Node::Block { .. }))
|
||||
.unwrap();
|
||||
let inner = if let Node::Block { children, .. } = outer {
|
||||
children
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|n| matches!(n, Node::Block { .. }))
|
||||
.unwrap()
|
||||
} else {
|
||||
panic!("Expected block with children");
|
||||
};
|
||||
(outer, inner)
|
||||
};
|
||||
|
||||
if let (
|
||||
Node::Block {
|
||||
span: outer_span, ..
|
||||
},
|
||||
Node::Block {
|
||||
if let Node::Block {
|
||||
span: inner_span, ..
|
||||
},
|
||||
) = (outer_if, inner_if)
|
||||
{
|
||||
// Verify outer if starts at the right line/column
|
||||
let (outer_line, outer_col) =
|
||||
ast.line_offsets.position_to_line_col(*outer_span.start());
|
||||
assert_eq!(
|
||||
(outer_line, outer_col),
|
||||
(1, 4),
|
||||
"Outer if should be indented"
|
||||
);
|
||||
} = inner_if
|
||||
{
|
||||
// Verify outer if starts at the right line/column
|
||||
let (outer_line, outer_col) =
|
||||
ast.line_offsets.position_to_line_col(*outer_span.start());
|
||||
assert_eq!(
|
||||
(outer_line, outer_col),
|
||||
(1, 4),
|
||||
"Outer if should be indented"
|
||||
);
|
||||
|
||||
// Verify inner if is more indented than outer if
|
||||
let (inner_line, inner_col) =
|
||||
ast.line_offsets.position_to_line_col(*inner_span.start());
|
||||
assert!(inner_col > outer_col, "Inner if should be more indented");
|
||||
assert!(inner_line > outer_line, "Inner if should be on later line");
|
||||
// Verify inner if is more indented than outer if
|
||||
let (inner_line, inner_col) =
|
||||
ast.line_offsets.position_to_line_col(*inner_span.start());
|
||||
assert!(inner_col > outer_col, "Inner if should be more indented");
|
||||
assert!(inner_line > outer_line, "Inner if should be on later line");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::ast::{Ast, AstError, BlockType, DjangoFilter, LineOffsets, Node, Span};
|
||||
use crate::tagspecs::TagSpec;
|
||||
use crate::tagspecs::{TagSpec, TagType};
|
||||
use crate::tokens::{Token, TokenStream, TokenType};
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -146,155 +146,102 @@ impl Parser {
|
|||
let tag_name = bits.first().ok_or(AstError::EmptyTag)?.clone();
|
||||
|
||||
let specs = TagSpec::load_builtin_specs().unwrap_or_default();
|
||||
|
||||
// Get the tag spec if it exists
|
||||
let tag_spec = specs.get(&tag_name);
|
||||
|
||||
// Check if this is a closing or branch tag
|
||||
for (_, spec) in specs.iter() {
|
||||
if Some(&tag_name) == spec.closing.as_ref()
|
||||
|| spec
|
||||
.branches
|
||||
.as_ref()
|
||||
.map(|ints| ints.iter().any(|i| i.name == tag_name))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Err(ParserError::ErrorSignal(Signal::SpecialTag(tag_name)));
|
||||
// Check if this is a closing tag
|
||||
if let Some(spec) = tag_spec {
|
||||
if let Some(closing) = &spec.closing {
|
||||
if tag_name == *closing {
|
||||
// This is a closing tag, return a signal instead of a node
|
||||
return Err(ParserError::Signal(Signal::ClosingTagFound(tag_name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tag_spec = specs.get(tag_name.as_str()).cloned();
|
||||
// Check if this is a branch tag
|
||||
if let Some(spec) = tag_spec {
|
||||
if let Some(branches) = &spec.branches {
|
||||
if branches.iter().any(|b| b.name == tag_name) {
|
||||
let mut children = Vec::new();
|
||||
while !self.is_at_end() {
|
||||
match self.peek()?.token_type() {
|
||||
TokenType::DjangoBlock(next_block) => {
|
||||
let next_bits: Vec<String> = next_block.split_whitespace().map(String::from).collect();
|
||||
if let Some(next_tag) = next_bits.first() {
|
||||
// If we hit another branch or closing tag, we're done
|
||||
if branches.iter().any(|b| &b.name == next_tag) ||
|
||||
spec.closing.as_ref().map(|s| s.as_str()) == Some(next_tag.as_str()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
children.push(self.next_node()?);
|
||||
}
|
||||
_ => children.push(self.next_node()?),
|
||||
}
|
||||
}
|
||||
return Ok(Node::Block {
|
||||
block_type: BlockType::Branch,
|
||||
name: tag_name,
|
||||
bits,
|
||||
children: Some(children),
|
||||
span: tag_span,
|
||||
tag_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a standard block
|
||||
let mut children = Vec::new();
|
||||
let mut current_branch: Option<(String, Vec<String>, Vec<Node>)> = None;
|
||||
let mut found_closing_tag = false;
|
||||
let mut found_closing = false;
|
||||
let mut end_pos = start_pos + s.len() as u32;
|
||||
|
||||
while !self.is_at_end() {
|
||||
match self.next_node() {
|
||||
Ok(node) => {
|
||||
if let Some((_, _, branch_children)) = &mut current_branch {
|
||||
branch_children.push(node);
|
||||
} else {
|
||||
children.push(node);
|
||||
}
|
||||
}
|
||||
Err(ParserError::ErrorSignal(Signal::SpecialTag(tag))) => {
|
||||
if let Some(spec) = &tag_spec {
|
||||
// Check if closing tag
|
||||
if spec.closing.as_deref() == Some(&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, 0); // Removed total_length initialization
|
||||
children.push(Node::Block {
|
||||
block_type: BlockType::Branch,
|
||||
name,
|
||||
bits,
|
||||
children: Some(branch_children),
|
||||
span: branch_span,
|
||||
tag_span,
|
||||
});
|
||||
}
|
||||
let closing_token = self.peek_previous()?;
|
||||
let closing_content = match closing_token.token_type() {
|
||||
TokenType::DjangoBlock(content) => content.len() + 5, // Add 5 for {% and %}
|
||||
_ => 0,
|
||||
};
|
||||
let closing_start = closing_token.start().unwrap_or(0);
|
||||
let total_length = (closing_start - start_pos as usize) + closing_content;
|
||||
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: closing_span,
|
||||
tag_span,
|
||||
});
|
||||
found_closing_tag = true;
|
||||
|
||||
// Set the final span length
|
||||
let span = Span::new(start_pos, total_length as u16);
|
||||
|
||||
let node = Node::Block {
|
||||
block_type: BlockType::Standard,
|
||||
name: tag_name,
|
||||
bits,
|
||||
children: Some(children),
|
||||
span,
|
||||
tag_span,
|
||||
};
|
||||
|
||||
return Ok(node);
|
||||
}
|
||||
// Check if intermediate tag
|
||||
if let Some(branches) = &spec.branches {
|
||||
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, 0); // Removed total_length initialization
|
||||
children.push(Node::Block {
|
||||
block_type: BlockType::Branch,
|
||||
name,
|
||||
bits,
|
||||
children: Some(branch_children),
|
||||
span: branch_span,
|
||||
tag_span,
|
||||
});
|
||||
match self.peek()?.token_type() {
|
||||
TokenType::DjangoBlock(next_block) => {
|
||||
let next_bits: Vec<String> = next_block.split_whitespace().map(String::from).collect();
|
||||
if let Some(next_tag) = next_bits.first() {
|
||||
// Check if this is a closing tag
|
||||
if let Some(spec) = tag_spec {
|
||||
if let Some(closing) = &spec.closing {
|
||||
if next_tag == closing {
|
||||
found_closing = true;
|
||||
let closing_token = self.consume()?;
|
||||
end_pos = closing_token.start().unwrap_or(0) as u32 + next_block.len() as u32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check if this is a branch tag
|
||||
if let Some(branches) = &spec.branches {
|
||||
if branches.iter().any(|b| &b.name == next_tag) {
|
||||
children.push(self.next_node()?);
|
||||
continue;
|
||||
}
|
||||
// Create new branch node
|
||||
let branch_bits = if branch.args {
|
||||
match &self.tokens[self.current - 1].token_type() {
|
||||
TokenType::DjangoBlock(content) => content
|
||||
.split_whitespace()
|
||||
.skip(1) // Skip the tag name
|
||||
.map(|s| s.to_string())
|
||||
.collect(),
|
||||
_ => vec![tag.clone()],
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
current_branch = Some((tag, branch_bits, Vec::new()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we get here, it's an unexpected tag
|
||||
let node = Node::Block {
|
||||
block_type: BlockType::Standard,
|
||||
name: tag_name.clone(),
|
||||
bits: bits.clone(),
|
||||
children: Some(children.clone()),
|
||||
span: Span::new(start_pos, 0), // Removed total_length initialization
|
||||
tag_span,
|
||||
};
|
||||
return Err(ParserError::Ast(AstError::UnexpectedTag(tag), Some(node)));
|
||||
children.push(self.next_node()?);
|
||||
}
|
||||
Err(ParserError::Ast(AstError::StreamError(kind), _)) if kind == "AtEnd" => {
|
||||
break;
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
_ => children.push(self.next_node()?),
|
||||
}
|
||||
}
|
||||
|
||||
let span = Span::new(start_pos, 0); // Removed total_length initialization
|
||||
|
||||
let node = Node::Block {
|
||||
block_type: BlockType::Standard,
|
||||
name: tag_name.clone(),
|
||||
bits,
|
||||
children: Some(children),
|
||||
span,
|
||||
tag_span,
|
||||
};
|
||||
|
||||
if !found_closing_tag {
|
||||
return Err(ParserError::Ast(
|
||||
AstError::UnclosedTag(tag_name),
|
||||
Some(node),
|
||||
if !found_closing && tag_spec.map_or(false, |s| s.closing.is_some()) {
|
||||
return Err(ParserError::from(
|
||||
AstError::UnclosedTag(tag_name.clone()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(node)
|
||||
Ok(Node::Block {
|
||||
block_type: BlockType::Standard,
|
||||
name: tag_name,
|
||||
bits,
|
||||
children: Some(children),
|
||||
span: Span::new(start_pos, (end_pos - start_pos) as u16),
|
||||
tag_span,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_django_variable(&mut self, s: &str) -> Result<Node, ParserError> {
|
||||
|
|
|
@ -17,58 +17,61 @@ nodes:
|
|||
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: 0
|
||||
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: 0
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 8
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endif
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 60
|
||||
length: 10
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 8
|
||||
span:
|
||||
start: 0
|
||||
length: 70
|
||||
length: 8
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 8
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: elif
|
||||
bits:
|
||||
- elif
|
||||
- x
|
||||
- "<"
|
||||
- "0"
|
||||
children: ~
|
||||
span:
|
||||
start: 22
|
||||
length: 10
|
||||
tag_span:
|
||||
start: 22
|
||||
length: 10
|
||||
- Text:
|
||||
content: Negative
|
||||
span:
|
||||
start: 38
|
||||
length: 8
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: else
|
||||
bits:
|
||||
- else
|
||||
children: ~
|
||||
span:
|
||||
start: 46
|
||||
length: 4
|
||||
tag_span:
|
||||
start: 46
|
||||
length: 4
|
||||
- Text:
|
||||
content: Zero
|
||||
span:
|
||||
start: 56
|
||||
length: 4
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 60
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 60
|
||||
length: 5
|
||||
line_offsets:
|
||||
- 0
|
||||
errors: []
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 527
|
||||
expression: ast
|
||||
snapshot_kind: text
|
||||
---
|
||||
nodes: []
|
||||
line_offsets:
|
||||
- 0
|
||||
errors:
|
||||
- UnclosedTag: if
|
|
@ -19,39 +19,41 @@ nodes:
|
|||
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: 0
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 17
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endfor
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 52
|
||||
length: 11
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 17
|
||||
span:
|
||||
start: 0
|
||||
length: 63
|
||||
length: 17
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 17
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: empty
|
||||
bits:
|
||||
- empty
|
||||
children: ~
|
||||
span:
|
||||
start: 33
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 33
|
||||
length: 5
|
||||
- Text:
|
||||
content: No items
|
||||
span:
|
||||
start: 44
|
||||
length: 8
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endfor
|
||||
bits:
|
||||
- endfor
|
||||
children: ~
|
||||
span:
|
||||
start: 52
|
||||
length: 6
|
||||
tag_span:
|
||||
start: 52
|
||||
length: 6
|
||||
line_offsets:
|
||||
- 0
|
||||
errors: []
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 518
|
||||
expression: ast
|
||||
snapshot_kind: text
|
||||
---
|
||||
nodes: []
|
||||
line_offsets:
|
||||
- 0
|
||||
errors:
|
||||
- UnclosedTag: for
|
|
@ -15,23 +15,24 @@ nodes:
|
|||
span:
|
||||
start: 30
|
||||
length: 7
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endif
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 37
|
||||
length: 10
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 24
|
||||
span:
|
||||
start: 0
|
||||
length: 47
|
||||
length: 24
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 24
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 37
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 37
|
||||
length: 5
|
||||
line_offsets:
|
||||
- 0
|
||||
errors: []
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 510
|
||||
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: []
|
|
@ -44,207 +44,214 @@ nodes:
|
|||
span:
|
||||
start: 86
|
||||
length: 5
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: for
|
||||
bits:
|
||||
- for
|
||||
- group
|
||||
- in
|
||||
- user.groups
|
||||
children:
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 125
|
||||
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: 10
|
||||
tag_span:
|
||||
start: 125
|
||||
length: 16
|
||||
span:
|
||||
start: 125
|
||||
length: 33
|
||||
tag_span:
|
||||
start: 125
|
||||
length: 16
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 168
|
||||
length: 9
|
||||
- Variable:
|
||||
bits:
|
||||
- group
|
||||
- name
|
||||
filters: []
|
||||
span:
|
||||
start: 171
|
||||
length: 10
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 193
|
||||
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: 10
|
||||
tag_span:
|
||||
start: 193
|
||||
length: 19
|
||||
span:
|
||||
start: 193
|
||||
length: 37
|
||||
tag_span:
|
||||
start: 193
|
||||
length: 19
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 240
|
||||
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: 10
|
||||
tag_span:
|
||||
start: 240
|
||||
length: 15
|
||||
span:
|
||||
start: 240
|
||||
length: 32
|
||||
tag_span:
|
||||
start: 240
|
||||
length: 15
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 278
|
||||
length: 5
|
||||
- Block:
|
||||
block_type: Branch
|
||||
name: empty
|
||||
bits: []
|
||||
children:
|
||||
- Text:
|
||||
content: "\n (no groups)\n "
|
||||
span:
|
||||
start: 298
|
||||
length: 25
|
||||
span:
|
||||
start: 86
|
||||
length: 0
|
||||
tag_span:
|
||||
start: 86
|
||||
length: 24
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endfor
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 314
|
||||
length: 11
|
||||
tag_span:
|
||||
start: 86
|
||||
length: 24
|
||||
span:
|
||||
start: 86
|
||||
length: 239
|
||||
tag_span:
|
||||
start: 86
|
||||
length: 24
|
||||
- Text:
|
||||
content: "\n"
|
||||
span:
|
||||
start: 327
|
||||
length: 1
|
||||
- Block:
|
||||
block_type: Branch
|
||||
name: else
|
||||
bits: []
|
||||
children:
|
||||
- Text:
|
||||
content: "\n Guest\n"
|
||||
span:
|
||||
start: 342
|
||||
length: 11
|
||||
span:
|
||||
start: 9
|
||||
length: 0
|
||||
tag_span:
|
||||
start: 9
|
||||
length: 24
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endif
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 348
|
||||
length: 10
|
||||
tag_span:
|
||||
start: 9
|
||||
length: 24
|
||||
span:
|
||||
start: 9
|
||||
length: 349
|
||||
length: 24
|
||||
tag_span:
|
||||
start: 9
|
||||
length: 24
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: for
|
||||
bits:
|
||||
- for
|
||||
- group
|
||||
- in
|
||||
- user.groups
|
||||
children:
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 125
|
||||
length: 9
|
||||
span:
|
||||
start: 86
|
||||
length: 24
|
||||
tag_span:
|
||||
start: 86
|
||||
length: 24
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: if
|
||||
bits:
|
||||
- if
|
||||
- forloop.first
|
||||
children:
|
||||
- Text:
|
||||
content: (
|
||||
span:
|
||||
start: 147
|
||||
length: 1
|
||||
span:
|
||||
start: 125
|
||||
length: 16
|
||||
tag_span:
|
||||
start: 125
|
||||
length: 16
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 148
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 148
|
||||
length: 5
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 168
|
||||
length: 9
|
||||
- Variable:
|
||||
bits:
|
||||
- group
|
||||
- name
|
||||
filters: []
|
||||
span:
|
||||
start: 171
|
||||
length: 10
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 193
|
||||
length: 9
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: if
|
||||
bits:
|
||||
- if
|
||||
- not
|
||||
- forloop.last
|
||||
children:
|
||||
- Text:
|
||||
content: ", "
|
||||
span:
|
||||
start: 218
|
||||
length: 2
|
||||
span:
|
||||
start: 193
|
||||
length: 19
|
||||
tag_span:
|
||||
start: 193
|
||||
length: 19
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 220
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 220
|
||||
length: 5
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 240
|
||||
length: 9
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: if
|
||||
bits:
|
||||
- if
|
||||
- forloop.last
|
||||
children:
|
||||
- Text:
|
||||
content: )
|
||||
span:
|
||||
start: 261
|
||||
length: 1
|
||||
span:
|
||||
start: 240
|
||||
length: 15
|
||||
tag_span:
|
||||
start: 240
|
||||
length: 15
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 262
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 262
|
||||
length: 5
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 278
|
||||
length: 5
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: empty
|
||||
bits:
|
||||
- empty
|
||||
children: ~
|
||||
span:
|
||||
start: 278
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 278
|
||||
length: 5
|
||||
- Text:
|
||||
content: "\n (no groups)\n "
|
||||
span:
|
||||
start: 298
|
||||
length: 25
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endfor
|
||||
bits:
|
||||
- endfor
|
||||
children: ~
|
||||
span:
|
||||
start: 314
|
||||
length: 6
|
||||
tag_span:
|
||||
start: 314
|
||||
length: 6
|
||||
- Text:
|
||||
content: "\n"
|
||||
span:
|
||||
start: 327
|
||||
length: 1
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: else
|
||||
bits:
|
||||
- else
|
||||
children: ~
|
||||
span:
|
||||
start: 327
|
||||
length: 4
|
||||
tag_span:
|
||||
start: 327
|
||||
length: 4
|
||||
- Text:
|
||||
content: "\n Guest\n"
|
||||
span:
|
||||
start: 342
|
||||
length: 11
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 348
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 348
|
||||
length: 5
|
||||
- Text:
|
||||
content: "!"
|
||||
span:
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 556
|
||||
expression: ast
|
||||
snapshot_kind: text
|
||||
---
|
||||
nodes:
|
||||
- Text:
|
||||
content: "Welcome, "
|
||||
span:
|
||||
start: 0
|
||||
length: 9
|
||||
line_offsets:
|
||||
- 0
|
||||
- 40
|
||||
- 82
|
||||
- 117
|
||||
- 160
|
||||
- 185
|
||||
- 232
|
||||
- 274
|
||||
- 290
|
||||
- 310
|
||||
- 327
|
||||
- 338
|
||||
- 348
|
||||
errors:
|
||||
- UnclosedTag: for
|
|
@ -11,56 +11,58 @@ nodes:
|
|||
- 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: 10
|
||||
tag_span:
|
||||
start: 23
|
||||
length: 14
|
||||
span:
|
||||
start: 23
|
||||
length: 45
|
||||
tag_span:
|
||||
start: 23
|
||||
length: 14
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endfor
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 69
|
||||
length: 11
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 17
|
||||
children: []
|
||||
span:
|
||||
start: 0
|
||||
length: 80
|
||||
length: 17
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 17
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: if
|
||||
bits:
|
||||
- if
|
||||
- item.active
|
||||
children:
|
||||
- Variable:
|
||||
bits:
|
||||
- item
|
||||
- name
|
||||
filters: []
|
||||
span:
|
||||
start: 46
|
||||
length: 9
|
||||
span:
|
||||
start: 23
|
||||
length: 14
|
||||
tag_span:
|
||||
start: 23
|
||||
length: 14
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 58
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 58
|
||||
length: 5
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endfor
|
||||
bits:
|
||||
- endfor
|
||||
children: ~
|
||||
span:
|
||||
start: 69
|
||||
length: 6
|
||||
tag_span:
|
||||
start: 69
|
||||
length: 6
|
||||
line_offsets:
|
||||
- 0
|
||||
errors: []
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 536
|
||||
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
|
||||
span:
|
||||
start: 23
|
||||
length: 14
|
||||
tag_span:
|
||||
start: 23
|
||||
length: 14
|
||||
span:
|
||||
start: 0
|
||||
length: 17
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 17
|
||||
line_offsets:
|
||||
- 0
|
||||
errors: []
|
|
@ -53,60 +53,61 @@ nodes:
|
|||
span:
|
||||
start: 252
|
||||
length: 9
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: for
|
||||
bits:
|
||||
- for
|
||||
- item
|
||||
- in
|
||||
- items
|
||||
children:
|
||||
- Text:
|
||||
content: "\n <span>"
|
||||
span:
|
||||
start: 288
|
||||
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: 11
|
||||
tag_span:
|
||||
start: 252
|
||||
length: 17
|
||||
span:
|
||||
start: 252
|
||||
length: 79
|
||||
tag_span:
|
||||
start: 252
|
||||
length: 17
|
||||
- Text:
|
||||
content: "\n <footer>Page Footer</footer>\n</div>"
|
||||
span:
|
||||
start: 337
|
||||
length: 40
|
||||
span:
|
||||
start: 48
|
||||
length: 0
|
||||
length: 24
|
||||
tag_span:
|
||||
start: 48
|
||||
length: 24
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: for
|
||||
bits:
|
||||
- for
|
||||
- item
|
||||
- in
|
||||
- items
|
||||
children:
|
||||
- Text:
|
||||
content: "\n <span>"
|
||||
span:
|
||||
start: 288
|
||||
length: 19
|
||||
- Variable:
|
||||
bits:
|
||||
- item
|
||||
filters: []
|
||||
span:
|
||||
start: 297
|
||||
length: 4
|
||||
- Text:
|
||||
content: "</span>\n "
|
||||
span:
|
||||
start: 304
|
||||
length: 16
|
||||
span:
|
||||
start: 252
|
||||
length: 17
|
||||
tag_span:
|
||||
start: 252
|
||||
length: 17
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endfor
|
||||
bits:
|
||||
- endfor
|
||||
children: ~
|
||||
span:
|
||||
start: 320
|
||||
length: 6
|
||||
tag_span:
|
||||
start: 320
|
||||
length: 6
|
||||
- Text:
|
||||
content: "\n <footer>Page Footer</footer>\n</div>"
|
||||
span:
|
||||
start: 337
|
||||
length: 40
|
||||
line_offsets:
|
||||
- 0
|
||||
- 24
|
||||
|
@ -120,5 +121,4 @@ line_offsets:
|
|||
- 312
|
||||
- 333
|
||||
- 366
|
||||
errors:
|
||||
- UnclosedTag: if
|
||||
errors: []
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 669
|
||||
expression: ast
|
||||
snapshot_kind: text
|
||||
---
|
||||
nodes:
|
||||
- Text:
|
||||
content: "<div class=\"container\">\n <h1>Header</h1>\n "
|
||||
span:
|
||||
start: 0
|
||||
length: 48
|
||||
line_offsets:
|
||||
- 0
|
||||
- 24
|
||||
- 44
|
||||
- 79
|
||||
- 131
|
||||
- 170
|
||||
- 184
|
||||
- 244
|
||||
- 276
|
||||
- 312
|
||||
- 333
|
||||
- 366
|
||||
errors:
|
||||
- UnclosedTag: if
|
|
@ -22,11 +22,10 @@ nodes:
|
|||
length: 9
|
||||
span:
|
||||
start: 0
|
||||
length: 0
|
||||
length: 17
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 17
|
||||
line_offsets:
|
||||
- 0
|
||||
errors:
|
||||
- UnclosedTag: for
|
||||
errors: []
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 630
|
||||
expression: ast
|
||||
snapshot_kind: text
|
||||
---
|
||||
nodes: []
|
||||
line_offsets:
|
||||
- 0
|
||||
errors:
|
||||
- UnclosedTag: for
|
|
@ -17,11 +17,10 @@ nodes:
|
|||
length: 7
|
||||
span:
|
||||
start: 0
|
||||
length: 0
|
||||
length: 24
|
||||
tag_span:
|
||||
start: 0
|
||||
length: 24
|
||||
line_offsets:
|
||||
- 0
|
||||
errors:
|
||||
- UnclosedTag: if
|
||||
errors: []
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 620
|
||||
expression: ast
|
||||
snapshot_kind: text
|
||||
---
|
||||
nodes: []
|
||||
line_offsets:
|
||||
- 0
|
||||
errors:
|
||||
- UnclosedTag: if
|
|
@ -54,73 +54,76 @@ nodes:
|
|||
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: 664
|
||||
length: 56
|
||||
- Block:
|
||||
block_type: Branch
|
||||
name: else
|
||||
bits: []
|
||||
children:
|
||||
- Text:
|
||||
content: "\n <span>User</span>\n "
|
||||
span:
|
||||
start: 730
|
||||
length: 55
|
||||
span:
|
||||
start: 621
|
||||
length: 0
|
||||
tag_span:
|
||||
start: 621
|
||||
length: 16
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endif
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 764
|
||||
length: 10
|
||||
tag_span:
|
||||
start: 621
|
||||
length: 16
|
||||
span:
|
||||
start: 621
|
||||
length: 153
|
||||
tag_span:
|
||||
start: 621
|
||||
length: 16
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 788
|
||||
length: 13
|
||||
- Block:
|
||||
block_type: Closing
|
||||
name: endif
|
||||
bits: []
|
||||
children: ~
|
||||
span:
|
||||
start: 788
|
||||
length: 10
|
||||
tag_span:
|
||||
start: 463
|
||||
length: 24
|
||||
span:
|
||||
start: 463
|
||||
length: 335
|
||||
length: 24
|
||||
tag_span:
|
||||
start: 463
|
||||
length: 24
|
||||
- Block:
|
||||
block_type: Standard
|
||||
name: if
|
||||
bits:
|
||||
- if
|
||||
- user.is_staff
|
||||
children:
|
||||
- Text:
|
||||
content: "\n <span>Admin</span>\n "
|
||||
span:
|
||||
start: 664
|
||||
length: 56
|
||||
span:
|
||||
start: 621
|
||||
length: 16
|
||||
tag_span:
|
||||
start: 621
|
||||
length: 16
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: else
|
||||
bits:
|
||||
- else
|
||||
children: ~
|
||||
span:
|
||||
start: 699
|
||||
length: 4
|
||||
tag_span:
|
||||
start: 699
|
||||
length: 4
|
||||
- Text:
|
||||
content: "\n <span>User</span>\n "
|
||||
span:
|
||||
start: 730
|
||||
length: 55
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 764
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 764
|
||||
length: 5
|
||||
- Text:
|
||||
content: "\n "
|
||||
span:
|
||||
start: 788
|
||||
length: 13
|
||||
- Block:
|
||||
block_type: Standalone
|
||||
name: endif
|
||||
bits:
|
||||
- endif
|
||||
children: ~
|
||||
span:
|
||||
start: 788
|
||||
length: 5
|
||||
tag_span:
|
||||
start: 788
|
||||
length: 5
|
||||
- Text:
|
||||
content: "\n </div>\n </body>\n</html>"
|
||||
span:
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
source: crates/djls-template-ast/src/parser.rs
|
||||
assertion_line: 712
|
||||
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
|
||||
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:
|
||||
- UnclosedTag: if
|
Loading…
Add table
Add a link
Reference in a new issue