This commit is contained in:
Josh Thomas 2025-01-04 23:26:19 -06:00
parent 0b8ca4061c
commit 660fc64b78
11 changed files with 326 additions and 313 deletions

View file

@ -36,7 +36,12 @@ impl Ast {
pub enum Node { pub enum Node {
Text(String), Text(String),
Comment(String), Comment(String),
Block(BlockNode), Block {
block_type: BlockType,
name: String,
bits: Vec<String>,
children: Option<Vec<Node>>,
},
Variable { Variable {
bits: Vec<String>, bits: Vec<String>,
filters: Vec<DjangoFilter>, filters: Vec<DjangoFilter>,
@ -44,21 +49,10 @@ pub enum Node {
} }
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]
pub enum BlockNode { pub enum BlockType {
Standard { Standard,
name: String, Branch,
bits: Vec<String>, Closing,
children: Vec<Node>,
},
Branch {
name: String,
bits: Vec<String>,
children: Vec<Node>,
},
Closing {
name: String,
bits: Vec<String>,
},
} }
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]

View file

@ -1,4 +1,4 @@
use crate::ast::{Ast, AstError, BlockNode, DjangoFilter, Node}; use crate::ast::{Ast, AstError, BlockType, DjangoFilter, Node};
use crate::tagspecs::TagSpec; use crate::tagspecs::TagSpec;
use crate::tokens::{Token, TokenStream, TokenType}; use crate::tokens::{Token, TokenStream, TokenType};
use thiserror::Error; use thiserror::Error;
@ -151,16 +151,19 @@ impl Parser {
if spec.closing.as_deref() == Some(&tag) { if spec.closing.as_deref() == Some(&tag) {
// If we have a current branch, add it to children // If we have a current branch, add it to children
if let Some((name, bits, branch_children)) = current_branch { if let Some((name, bits, branch_children)) = current_branch {
children.push(Node::Block(BlockNode::Branch { children.push(Node::Block {
block_type: BlockType::Branch,
name, name,
bits, bits,
children: branch_children, children: Some(branch_children),
})); });
} }
children.push(Node::Block(BlockNode::Closing { children.push(Node::Block {
block_type: BlockType::Closing,
name: tag, name: tag,
bits: vec![], bits: vec![],
})); children: None,
});
found_closing_tag = true; found_closing_tag = true;
break; break;
} }
@ -169,11 +172,12 @@ impl Parser {
if let Some(branch) = branches.iter().find(|i| i.name == tag) { if let Some(branch) = branches.iter().find(|i| i.name == tag) {
// If we have a current branch, add it to children // If we have a current branch, add it to children
if let Some((name, bits, branch_children)) = current_branch { if let Some((name, bits, branch_children)) = current_branch {
children.push(Node::Block(BlockNode::Branch { children.push(Node::Block {
block_type: BlockType::Branch,
name, name,
bits, bits,
children: branch_children, children: Some(branch_children),
})); });
} }
// Create new branch node // Create new branch node
let branch_bits = if branch.args { let branch_bits = if branch.args {
@ -194,11 +198,12 @@ impl Parser {
} }
} }
// If we get here, it's an unexpected tag // If we get here, it's an unexpected tag
let node = Node::Block(BlockNode::Standard { let node = Node::Block {
block_type: BlockType::Standard,
name: tag_name.clone(), name: tag_name.clone(),
bits: bits.clone(), bits: bits.clone(),
children: children.clone(), children: Some(children.clone()),
}); };
return Err(ParserError::Ast(AstError::UnexpectedTag(tag), Some(node))); return Err(ParserError::Ast(AstError::UnexpectedTag(tag), Some(node)));
} }
Err(ParserError::Ast(AstError::StreamError(kind), _)) if kind == "AtEnd" => { Err(ParserError::Ast(AstError::StreamError(kind), _)) if kind == "AtEnd" => {
@ -208,11 +213,12 @@ impl Parser {
} }
} }
let node = Node::Block(BlockNode::Standard { let node = Node::Block {
block_type: BlockType::Standard,
name: tag_name.clone(), name: tag_name.clone(),
bits, bits,
children, children: Some(children),
}); };
if !found_closing_tag { if !found_closing_tag {
return Err(ParserError::Ast( return Err(ParserError::Ast(

View file

@ -4,32 +4,33 @@ expression: ast
--- ---
nodes: nodes:
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- x - x
- ">" - ">"
- "0" - "0"
children: children:
- Text: Positive - Text: Positive
- Block: - Block:
Branch: block_type: Branch
name: elif name: elif
bits: bits:
- x - x
- "<" - "<"
- "0" - "0"
children: children:
- Text: Negative - Text: Negative
- Block: - Block:
Branch: block_type: Branch
name: else name: else
bits: [] bits: []
children: children:
- Text: Zero - Text: Zero
- Block: - Block:
Closing: block_type: Closing
name: endif name: endif
bits: [] bits: []
children: ~
errors: [] errors: []

View file

@ -4,26 +4,27 @@ expression: ast
--- ---
nodes: nodes:
- Block: - Block:
Standard: block_type: Standard
name: for name: for
bits: bits:
- for - for
- item - item
- in - in
- items - items
children: children:
- Variable: - Variable:
bits: bits:
- item - item
filters: [] filters: []
- Block: - Block:
Branch: block_type: Branch
name: empty name: empty
bits: [] bits: []
children: children:
- Text: No items - Text: No items
- Block: - Block:
Closing: block_type: Closing
name: endfor name: endfor
bits: [] bits: []
children: ~
errors: [] errors: []

View file

@ -4,15 +4,16 @@ expression: ast
--- ---
nodes: nodes:
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- user.is_authenticated - user.is_authenticated
children: children:
- Text: Welcome - Text: Welcome
- Block: - Block:
Closing: block_type: Closing
name: endif name: endif
bits: [] bits: []
children: ~
errors: [] errors: []

View file

@ -5,100 +5,105 @@ expression: ast
nodes: nodes:
- Text: "Welcome, " - Text: "Welcome, "
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- user.is_authenticated - user.is_authenticated
children: children:
- Text: "\n " - Text: "\n "
- Variable: - Variable:
bits: bits:
- user - user
- name - name
filters: filters:
- name: title - name: title
arguments: [] arguments: []
- name: default - name: default
arguments: arguments:
- "'Guest'" - "'Guest'"
- Text: "\n " - Text: "\n "
- Block: - Block:
Standard: block_type: Standard
name: for name: for
bits: bits:
- for - for
- group - group
- in - in
- user.groups - user.groups
children: children:
- Text: "\n " - Text: "\n "
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- forloop.first - forloop.first
children: children:
- Text: ( - Text: (
- Block: - Block:
Closing: block_type: Closing
name: endif name: endif
bits: []
- Text: "\n "
- Variable:
bits:
- group
- name
filters: []
- Text: "\n "
- Block:
Standard:
name: if
bits:
- if
- not
- forloop.last
children:
- Text: ", "
- Block:
Closing:
name: endif
bits: []
- Text: "\n "
- Block:
Standard:
name: if
bits:
- if
- forloop.last
children:
- Text: )
- Block:
Closing:
name: endif
bits: []
- Text: "\n "
- Block:
Branch:
name: empty
bits: [] bits: []
children: children: ~
- Text: "\n (no groups)\n " - Text: "\n "
- Block: - Variable:
Closing: bits:
name: endfor - group
- name
filters: []
- Text: "\n "
- Block:
block_type: Standard
name: if
bits:
- if
- not
- forloop.last
children:
- Text: ", "
- Block:
block_type: Closing
name: endif
bits: [] bits: []
- Text: "\n" children: ~
- Block: - Text: "\n "
Branch: - Block:
name: else block_type: Standard
bits: [] name: if
children: bits:
- Text: "\n Guest\n" - if
- Block: - forloop.last
Closing: children:
name: endif - Text: )
bits: [] - Block:
block_type: Closing
name: endif
bits: []
children: ~
- Text: "\n "
- Block:
block_type: Branch
name: empty
bits: []
children:
- Text: "\n (no groups)\n "
- Block:
block_type: Closing
name: endfor
bits: []
children: ~
- Text: "\n"
- Block:
block_type: Branch
name: else
bits: []
children:
- Text: "\n Guest\n"
- Block:
block_type: Closing
name: endif
bits: []
children: ~
- Text: "!" - Text: "!"
errors: [] errors: []

View file

@ -4,32 +4,34 @@ expression: ast
--- ---
nodes: nodes:
- Block: - Block:
Standard: block_type: Standard
name: for name: for
bits: bits:
- for - for
- item - item
- in - in
- items - items
children: children:
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- item.active - item.active
children: children:
- Variable: - Variable:
bits: bits:
- item - item
- name - name
filters: [] filters: []
- Block: - Block:
Closing: block_type: Closing
name: endif name: endif
bits: [] bits: []
- Block: children: ~
Closing: - Block:
name: endfor block_type: Closing
bits: [] name: endfor
bits: []
children: ~
errors: [] errors: []

View file

@ -5,42 +5,43 @@ expression: ast
nodes: nodes:
- Text: "<div class=\"container\">\n <h1>Header</h1>\n " - Text: "<div class=\"container\">\n <h1>Header</h1>\n "
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- user.is_authenticated - user.is_authenticated
children: children:
- Text: "\n " - Text: "\n "
- Comment: This if is unclosed which does matter - Comment: This if is unclosed which does matter
- Text: "\n <p>Welcome " - Text: "\n <p>Welcome "
- Variable: - Variable:
bits: bits:
- user - user
- name - name
filters: [] filters: []
- Text: "</p>\n <div>\n " - Text: "</p>\n <div>\n "
- Comment: "This div is unclosed which doesn't matter" - Comment: "This div is unclosed which doesn't matter"
- Text: "\n " - Text: "\n "
- Block: - Block:
Standard: block_type: Standard
name: for name: for
bits: bits:
- for - for
- item - item
- in - in
- items - items
children: children:
- Text: "\n <span>" - Text: "\n <span>"
- Variable: - Variable:
bits: bits:
- item - item
filters: [] filters: []
- Text: "</span>\n " - Text: "</span>\n "
- Block: - Block:
Closing: block_type: Closing
name: endfor name: endfor
bits: [] bits: []
- Text: "\n <footer>Page Footer</footer>\n</div>" children: ~
- Text: "\n <footer>Page Footer</footer>\n</div>"
errors: errors:
- UnclosedTag: if - UnclosedTag: if

View file

@ -4,18 +4,18 @@ expression: ast
--- ---
nodes: nodes:
- Block: - Block:
Standard: block_type: Standard
name: for name: for
bits: bits:
- for - for
- item - item
- in - in
- items - items
children: children:
- Variable: - Variable:
bits: bits:
- item - item
- name - name
filters: [] filters: []
errors: errors:
- UnclosedTag: for - UnclosedTag: for

View file

@ -4,12 +4,12 @@ expression: ast
--- ---
nodes: nodes:
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- user.is_authenticated - user.is_authenticated
children: children:
- Text: Welcome - Text: Welcome
errors: errors:
- UnclosedTag: if - UnclosedTag: if

View file

@ -5,48 +5,50 @@ expression: ast
nodes: nodes:
- Text: "<!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 " - Text: "<!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 "
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- user.is_authenticated - user.is_authenticated
children: children:
- Text: "\n " - Text: "\n "
- Comment: Welcome message - Comment: Welcome message
- Text: "\n <h1>Welcome, " - Text: "\n <h1>Welcome, "
- Variable: - Variable:
bits: bits:
- user - user
- name - name
filters: filters:
- name: title - name: title
arguments: [] arguments: []
- name: default - name: default
arguments: arguments:
- "'Guest'" - "'Guest'"
- Text: "!</h1>\n " - Text: "!</h1>\n "
- Block: - Block:
Standard: block_type: Standard
name: if name: if
bits: bits:
- if - if
- user.is_staff - user.is_staff
children: children:
- Text: "\n <span>Admin</span>\n " - Text: "\n <span>Admin</span>\n "
- Block: - Block:
Branch: block_type: Branch
name: else name: else
bits: [] bits: []
children: children:
- Text: "\n <span>User</span>\n " - Text: "\n <span>User</span>\n "
- Block: - Block:
Closing: block_type: Closing
name: endif name: endif
bits: [] bits: []
- Text: "\n " children: ~
- Block: - Text: "\n "
Closing: - Block:
name: endif block_type: Closing
bits: [] name: endif
bits: []
children: ~
- Text: "\n </div>\n </body>\n</html>" - Text: "\n </div>\n </body>\n</html>"
errors: [] errors: []