Skip to content

Commit 1295247

Browse files
remove variable type
1 parent 360276a commit 1295247

File tree

4 files changed

+43
-67
lines changed

4 files changed

+43
-67
lines changed

crates/djls-template-ast/SPEC.md

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,6 @@ pub enum Block {
127127
tag: Tag,
128128
template_name: String,
129129
},
130-
Variable {
131-
tag: Tag,
132-
},
133130
Closing {
134131
tag: Tag,
135132
},
@@ -231,21 +228,6 @@ Examples:
231228
- `{% include "template.html" %}`
232229
- `{% extends "base.html" %}`
233230

234-
##### `Block::Variable`
235-
236-
Represents tags that output a value directly.
237-
238-
```rust
239-
Block::Variable {
240-
tag: Tag, // The Tag of the variable tag
241-
}
242-
```
243-
244-
Examples:
245-
246-
- `{% cycle %}`
247-
- `{% firstof %}`
248-
249231
##### `Block::Closing`
250232

251233
Represents closing tags corresponding to opening block tags.
@@ -270,15 +252,21 @@ Tag Specifications (TagSpecs) define how tags are parsed and understood. They al
270252

271253
```toml
272254
[package.module.path.tag_name] # Path where tag is registered, e.g., django.template.defaulttags
273-
type = "block" | "inclusion" | "tag" | "variable"
255+
type = "block" | "inclusion" | "tag"
274256
closing = "closing_tag_name" # For block tags that require a closing tag
275257
branches = ["branch_tag_name", ...] # For block tags that support branches
276258

277-
[[package.module.path.tag_name.args]]
278-
name = "argument_name"
279-
required = true | false
259+
# Arguments can be positional (matched by order) or keyword (matched by name)
260+
args = [
261+
# Positional argument (position inferred from array index)
262+
{ name = "setting", required = true, allowed_values = ["on", "off"] },
263+
# Keyword argument
264+
{ name = "key", required = false, is_kwarg = true }
265+
]
280266
```
281267

268+
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`.
269+
282270
### Tag Types
283271

284272
- `block`: Tags that wrap content and require a closing tag
@@ -301,13 +289,6 @@ required = true | false
301289
{% csrf_token %}
302290
```
303291

304-
- `variable`: Tags that output a value directly
305-
306-
```django
307-
{% cycle 'odd' 'even' %}
308-
{% firstof var1 var2 var3 %}
309-
```
310-
311292
### Configuration
312293

313294
- **Built-in TagSpecs**: The parser includes TagSpecs for Django's built-in tags and popular third-party tags.
@@ -322,30 +303,33 @@ required = true | false
322303
type = "block"
323304
closing = "endif"
324305
branches = ["elif", "else"]
325-
326-
[[django.template.defaulttags.if.args]]
327-
name = "condition"
328-
required = true
306+
args = [{ name = "condition", required = true }]
329307
```
330308

331309
#### Include Tag
332310

333311
```toml
334312
[django.template.defaulttags.includes]
335313
type = "inclusion"
314+
args = [{ name = "template_name", required = true }]
315+
```
316+
317+
#### Autoescape Tag
336318

337-
[[django.template.defaulttags.includes.args]]
338-
name = "template_name"
339-
required = true
319+
```toml
320+
[django.template.defaulttags.autoescape]
321+
type = "block"
322+
closing = "endautoescape"
323+
args = [{ name = "setting", required = true, allowed_values = ["on", "off"] }]
340324
```
341325

342-
#### Custom Tag
326+
#### Custom Tag with Kwargs
343327

344328
```toml
345329
[my_module.templatetags.my_tags.my_custom_tag]
346330
type = "tag"
347-
348-
{[my_module.templatetags.my_tags.my_custom_tag.args]]
349-
name = "arg1"
350-
required = false
331+
args = [
332+
{ name = "arg1", required = true },
333+
{ name = "kwarg1", required = false, is_kwarg = true }
334+
]
351335
```

crates/djls-template-ast/src/ast.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,6 @@ pub enum Block {
162162
tag: Tag,
163163
template_name: String,
164164
},
165-
Variable {
166-
tag: Tag,
167-
},
168165
Closing {
169166
tag: Tag,
170167
},
@@ -177,7 +174,6 @@ impl Block {
177174
| Self::Branch { tag, .. }
178175
| Self::Tag { tag }
179176
| Self::Inclusion { tag, .. }
180-
| Self::Variable { tag }
181177
| Self::Closing { tag } => tag,
182178
}
183179
}

crates/djls-template-ast/src/parser.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ impl Parser {
110110
Some(spec) => match spec.tag_type {
111111
TagType::Block => self.parse_block_tag(tag, spec),
112112
TagType::Tag => Ok(Node::Block(Block::Tag { tag })),
113-
TagType::Variable => Ok(Node::Block(Block::Variable { tag })),
114113
TagType::Inclusion => {
115114
let template_name = tag.bits.get(1).cloned().unwrap_or_default();
116115
Ok(Node::Block(Block::Inclusion { tag, template_name }))

crates/djls-template-ast/src/tagspecs.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,6 @@ impl TagSpec {
117117
let name = prefix.map_or_else(String::new, |p| {
118118
p.split('.').last().unwrap_or(p).to_string()
119119
});
120-
eprintln!(
121-
"Found tag spec at '{}', using name '{}'",
122-
prefix.unwrap_or(""),
123-
name
124-
);
125120
specs.insert(name, tag_spec);
126121
}
127122
Err(_) => {
@@ -131,7 +126,6 @@ impl TagSpec {
131126
None => key.clone(),
132127
Some(p) => format!("{}.{}", p, key),
133128
};
134-
eprintln!("Recursing into prefix: {}", new_prefix);
135129
Self::extract_specs(value, Some(&new_prefix), specs)?;
136130
}
137131
}
@@ -146,13 +140,16 @@ pub enum TagType {
146140
Block,
147141
Tag,
148142
Inclusion,
149-
Variable,
150143
}
151144

152145
#[derive(Clone, Debug, Deserialize)]
153146
pub struct ArgSpec {
154147
pub name: String,
155148
pub required: bool,
149+
#[serde(default)]
150+
pub allowed_values: Option<Vec<String>>,
151+
#[serde(default)]
152+
pub is_kwarg: bool,
156153
}
157154

158155
impl ArgSpec {
@@ -179,12 +176,8 @@ mod tests {
179176

180177
assert!(!specs.0.is_empty(), "Should have loaded at least one spec");
181178

182-
for (name, spec) in &specs.0 {
179+
for name in specs.0.keys() {
183180
assert!(!name.is_empty(), "Tag name should not be empty");
184-
assert!(
185-
spec.tag_type == TagType::Block || spec.tag_type == TagType::Variable,
186-
"Tag type should be block or variable"
187-
);
188181
}
189182
Ok(())
190183
}
@@ -193,31 +186,35 @@ mod tests {
193186
fn test_builtin_django_tags() -> Result<(), anyhow::Error> {
194187
let specs = TagSpecs::load_builtin_specs()?;
195188

196-
let expected_tags = ["block", "for", "if"];
197-
let missing_tags = [
189+
let expected_tags = [
198190
"autoescape",
191+
"block",
199192
"comment",
200-
"csrf_token",
201193
"cycle",
202194
"debug",
203195
"extends",
204196
"filter",
197+
"for",
205198
"firstof",
206-
"ifchanged",
199+
"if",
207200
"include",
208201
"load",
209-
"lorem",
210202
"now",
211-
"querystring", // 5.1
212-
"regroup",
213-
"resetcycle",
214203
"spaceless",
215204
"templatetag",
216205
"url",
217206
"verbatim",
218-
"widthratio",
219207
"with",
220208
];
209+
let missing_tags = [
210+
"csrf_token",
211+
"ifchanged",
212+
"lorem",
213+
"querystring", // 5.1
214+
"regroup",
215+
"resetcycle",
216+
"widthratio",
217+
];
221218

222219
for tag in expected_tags {
223220
assert!(specs.get(tag).is_some(), "{} tag should be present", tag);

0 commit comments

Comments
 (0)