remove variable type

This commit is contained in:
Josh Thomas 2025-01-06 21:32:39 -06:00
parent 360276af1a
commit 1295247aa9
4 changed files with 44 additions and 68 deletions

View file

@ -127,9 +127,6 @@ pub enum Block {
tag: Tag,
template_name: String,
},
Variable {
tag: Tag,
},
Closing {
tag: Tag,
},
@ -231,21 +228,6 @@ Examples:
- `{% include "template.html" %}`
- `{% extends "base.html" %}`
##### `Block::Variable`
Represents tags that output a value directly.
```rust
Block::Variable {
tag: Tag, // The Tag of the variable tag
}
```
Examples:
- `{% cycle %}`
- `{% firstof %}`
##### `Block::Closing`
Represents closing tags corresponding to opening block tags.
@ -270,15 +252,21 @@ Tag Specifications (TagSpecs) define how tags are parsed and understood. They al
```toml
[package.module.path.tag_name] # Path where tag is registered, e.g., django.template.defaulttags
type = "block" | "inclusion" | "tag" | "variable"
type = "block" | "inclusion" | "tag"
closing = "closing_tag_name" # For block tags that require a closing tag
branches = ["branch_tag_name", ...] # For block tags that support branches
[[package.module.path.tag_name.args]]
name = "argument_name"
required = true | false
# Arguments can be positional (matched by order) or keyword (matched by name)
args = [
# Positional argument (position inferred from array index)
{ name = "setting", required = true, allowed_values = ["on", "off"] },
# Keyword argument
{ name = "key", required = false, is_kwarg = true }
]
```
The `name` field in args should match the internal name used in Django's node implementation. For example, the `autoescape` tag's argument is stored as `setting` in Django's `AutoEscapeControlNode`.
### Tag Types
- `block`: Tags that wrap content and require a closing tag
@ -301,13 +289,6 @@ required = true | false
{% csrf_token %}
```
- `variable`: Tags that output a value directly
```django
{% cycle 'odd' 'even' %}
{% firstof var1 var2 var3 %}
```
### Configuration
- **Built-in TagSpecs**: The parser includes TagSpecs for Django's built-in tags and popular third-party tags.
@ -322,10 +303,7 @@ required = true | false
type = "block"
closing = "endif"
branches = ["elif", "else"]
[[django.template.defaulttags.if.args]]
name = "condition"
required = true
args = [{ name = "condition", required = true }]
```
#### Include Tag
@ -333,19 +311,25 @@ required = true
```toml
[django.template.defaulttags.includes]
type = "inclusion"
[[django.template.defaulttags.includes.args]]
name = "template_name"
required = true
args = [{ name = "template_name", required = true }]
```
#### Custom Tag
#### Autoescape Tag
```toml
[django.template.defaulttags.autoescape]
type = "block"
closing = "endautoescape"
args = [{ name = "setting", required = true, allowed_values = ["on", "off"] }]
```
#### Custom Tag with Kwargs
```toml
[my_module.templatetags.my_tags.my_custom_tag]
type = "tag"
{[my_module.templatetags.my_tags.my_custom_tag.args]]
name = "arg1"
required = false
args = [
{ name = "arg1", required = true },
{ name = "kwarg1", required = false, is_kwarg = true }
]
```

View file

@ -162,9 +162,6 @@ pub enum Block {
tag: Tag,
template_name: String,
},
Variable {
tag: Tag,
},
Closing {
tag: Tag,
},
@ -177,7 +174,6 @@ impl Block {
| Self::Branch { tag, .. }
| Self::Tag { tag }
| Self::Inclusion { tag, .. }
| Self::Variable { tag }
| Self::Closing { tag } => tag,
}
}

View file

@ -110,7 +110,6 @@ impl Parser {
Some(spec) => match spec.tag_type {
TagType::Block => self.parse_block_tag(tag, spec),
TagType::Tag => Ok(Node::Block(Block::Tag { tag })),
TagType::Variable => Ok(Node::Block(Block::Variable { tag })),
TagType::Inclusion => {
let template_name = tag.bits.get(1).cloned().unwrap_or_default();
Ok(Node::Block(Block::Inclusion { tag, template_name }))

View file

@ -117,11 +117,6 @@ impl TagSpec {
let name = prefix.map_or_else(String::new, |p| {
p.split('.').last().unwrap_or(p).to_string()
});
eprintln!(
"Found tag spec at '{}', using name '{}'",
prefix.unwrap_or(""),
name
);
specs.insert(name, tag_spec);
}
Err(_) => {
@ -131,7 +126,6 @@ impl TagSpec {
None => key.clone(),
Some(p) => format!("{}.{}", p, key),
};
eprintln!("Recursing into prefix: {}", new_prefix);
Self::extract_specs(value, Some(&new_prefix), specs)?;
}
}
@ -146,13 +140,16 @@ pub enum TagType {
Block,
Tag,
Inclusion,
Variable,
}
#[derive(Clone, Debug, Deserialize)]
pub struct ArgSpec {
pub name: String,
pub required: bool,
#[serde(default)]
pub allowed_values: Option<Vec<String>>,
#[serde(default)]
pub is_kwarg: bool,
}
impl ArgSpec {
@ -179,12 +176,8 @@ mod tests {
assert!(!specs.0.is_empty(), "Should have loaded at least one spec");
for (name, spec) in &specs.0 {
for name in specs.0.keys() {
assert!(!name.is_empty(), "Tag name should not be empty");
assert!(
spec.tag_type == TagType::Block || spec.tag_type == TagType::Variable,
"Tag type should be block or variable"
);
}
Ok(())
}
@ -193,31 +186,35 @@ mod tests {
fn test_builtin_django_tags() -> Result<(), anyhow::Error> {
let specs = TagSpecs::load_builtin_specs()?;
let expected_tags = ["block", "for", "if"];
let missing_tags = [
let expected_tags = [
"autoescape",
"block",
"comment",
"csrf_token",
"cycle",
"debug",
"extends",
"filter",
"for",
"firstof",
"ifchanged",
"if",
"include",
"load",
"lorem",
"now",
"querystring", // 5.1
"regroup",
"resetcycle",
"spaceless",
"templatetag",
"url",
"verbatim",
"widthratio",
"with",
];
let missing_tags = [
"csrf_token",
"ifchanged",
"lorem",
"querystring", // 5.1
"regroup",
"resetcycle",
"widthratio",
];
for tag in expected_tags {
assert!(specs.get(tag).is_some(), "{} tag should be present", tag);