Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6105fd9002 | ||
|
|
0caa8c104b |
No files matched your search
+25
-6
@@ -144,11 +144,12 @@ function simpleTag($, tag, args = true, kwargs = true) {
|
||||
repeat(part(seq($._kwarg_name, $.identifier, "=", $.filtered_value))),
|
||||
);
|
||||
} else if (kwargs) {
|
||||
parts.unshift($._tag_open);
|
||||
// a known signature: any of the names it accepts, in any order, none twice
|
||||
const named = Object.entries(kwargs).map(([name, value]) =>
|
||||
part(seq(name, "=", value)),
|
||||
part(seq($._kwarg_name, name, "=", value)),
|
||||
);
|
||||
parts.push(optional(arrangements(named)));
|
||||
parts.push(repeat(choice(...named)));
|
||||
}
|
||||
return block(tag, ...parts, optional(asVariable($)));
|
||||
}
|
||||
@@ -527,7 +528,7 @@ const django = grammar({
|
||||
seq(
|
||||
$._bt_option,
|
||||
choice(
|
||||
seq(part("with"), $._translate_kwargs),
|
||||
seq(part("with"), $._tag_kwargs),
|
||||
part("context", $.filtered_value),
|
||||
part("trimmed"),
|
||||
part("asvar", field("variable", $.identifier)),
|
||||
@@ -542,8 +543,13 @@ const django = grammar({
|
||||
),
|
||||
),
|
||||
_translate_body: ($) => repeat1(choice($.content, $.template_variable)),
|
||||
/** The "with" option of blocktranslate takes at least one of these. */
|
||||
_translate_kwargs: ($) =>
|
||||
/**
|
||||
* The "with" option of blocktranslate and of include takes at least one of
|
||||
* these. Django lets a name repeat here — token_kwargs builds a dict and
|
||||
* the later value wins — so unlike a simple_tag's arguments they are not
|
||||
* guarded.
|
||||
*/
|
||||
_tag_kwargs: ($) =>
|
||||
repeat1(
|
||||
part(seq(field("variable", $.identifier), "=", $.filtered_value)),
|
||||
),
|
||||
@@ -674,7 +680,20 @@ const django = grammar({
|
||||
optional(seq(block("else"), optional($.template))),
|
||||
block("endifchanged"),
|
||||
),
|
||||
include: ($) => block("include", part($.filtered_value)),
|
||||
/**
|
||||
* do_include takes "with" and "only" in either order and refuses one it has
|
||||
* already been given, and "with" needs at least one argument. It calls
|
||||
* token_kwargs with support_legacy=False, so "{% include "t" with a as b %}"
|
||||
* is an error here as it is there, unlike the same clause in "{% with %}".
|
||||
*/
|
||||
include: ($) =>
|
||||
block(
|
||||
"include",
|
||||
part($.filtered_value),
|
||||
optional(
|
||||
arrangements([seq(part("with"), $._tag_kwargs), part("only")]),
|
||||
),
|
||||
),
|
||||
/** django.templatetags.i18n. The language tag takes the one argument. */
|
||||
language_group: ($) =>
|
||||
seq(
|
||||
|
||||
+148
-28
@@ -1980,7 +1980,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_translate_kwargs"
|
||||
"name": "_tag_kwargs"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2125,7 +2125,7 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"_translate_kwargs": {
|
||||
"_tag_kwargs": {
|
||||
"type": "REPEAT1",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
@@ -2501,6 +2501,10 @@
|
||||
"value": "csp_nonce_attr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_tag_open"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
@@ -2523,6 +2527,8 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
@@ -2535,6 +2541,10 @@
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_kwarg_name"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "media"
|
||||
@@ -2550,11 +2560,9 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
@@ -4695,6 +4703,134 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "with"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_tag_kwargs"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "with"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_tag_kwargs"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "only"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "only"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "only"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "with"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_tag_kwargs"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
@@ -7825,25 +7961,12 @@
|
||||
},
|
||||
"extras": [],
|
||||
"conflicts": [
|
||||
[
|
||||
"template"
|
||||
],
|
||||
[
|
||||
"predicate"
|
||||
],
|
||||
[
|
||||
"library",
|
||||
"load"
|
||||
],
|
||||
[
|
||||
"_translate_option"
|
||||
],
|
||||
[
|
||||
"_filtered_value_spaced"
|
||||
],
|
||||
[
|
||||
"_filter_expression_spaced"
|
||||
]
|
||||
["template"],
|
||||
["predicate"],
|
||||
["library", "load"],
|
||||
["_translate_option"],
|
||||
["_filtered_value_spaced"],
|
||||
["_filter_expression_spaced"]
|
||||
],
|
||||
"precedences": [],
|
||||
"externals": [
|
||||
@@ -7897,10 +8020,7 @@
|
||||
}
|
||||
],
|
||||
"inline": [],
|
||||
"supertypes": [
|
||||
"template_tag",
|
||||
"template_block_groups"
|
||||
],
|
||||
"supertypes": ["template_tag", "template_block_groups"],
|
||||
"reserved": {
|
||||
"global": [
|
||||
{
|
||||
|
||||
+15
-1
@@ -1377,10 +1377,20 @@
|
||||
"named": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"variable": {
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
@@ -2714,6 +2724,10 @@
|
||||
"type": "on",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "only",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "openblock",
|
||||
"named": false
|
||||
|
||||
+56427
-56036
File diff suppressed because it is too large.
Load diff
+8
-8
@@ -68,14 +68,16 @@ struct Scanner {
|
||||
/* one bit per option of the blocktranslate tag being read, by the order of
|
||||
* translate_options. Kept out of the union below, whose members share their
|
||||
* storage with each other. */
|
||||
uint8_t translate_seen;
|
||||
/* the "name=value" argument names the tag being read has been given, each
|
||||
* followed by NAME_SEP. parse_bits refuses a repeated keyword argument, and
|
||||
* the set of names is open, so this remembers the names rather than a mask
|
||||
* of known ones. Kept out of the union, as translate_seen is. */
|
||||
Name seen_kwargs;
|
||||
union {
|
||||
struct {
|
||||
uint8_t translate_seen;
|
||||
Name seen_kwargs;
|
||||
Stack stack;
|
||||
};
|
||||
char error [ERROR_SIZE];
|
||||
};
|
||||
};
|
||||
@@ -89,14 +91,12 @@ static enum TokenType pop_token_for_kind(TagKind kind) {
|
||||
}
|
||||
|
||||
static void reset_scanner(struct Scanner *const scanner) {
|
||||
if (scanner->has_error) {
|
||||
// sets everything to 0 values: 0, '\0', false, null
|
||||
memset(&scanner, 0, sizeof(scanner));
|
||||
} else {
|
||||
scanner->translate_seen = 0;
|
||||
array_delete(&scanner->seen_kwargs);
|
||||
if (scanner->has_error) {
|
||||
scanner->error[0] = '\0';
|
||||
scanner->has_error = false;
|
||||
// the error shares storage with the stack, which is now meaningless
|
||||
memset(&scanner->stack, 0, sizeof(scanner->stack));
|
||||
} else {
|
||||
for (unsigned i = 0; i < scanner->stack.size; ++i) {
|
||||
array_delete(&array_get(&scanner->stack, i)->name);
|
||||
}
|
||||
|
||||
@@ -31,3 +31,228 @@ Include With Variable
|
||||
(variable_attribute
|
||||
(identifier)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include With A Filtered Name
|
||||
==================
|
||||
|
||||
{% include "t.html"|upper %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(include
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string)))
|
||||
(filter_expression
|
||||
(filter))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include Only
|
||||
==================
|
||||
|
||||
{% include "t.html" only %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(include
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include With Context
|
||||
==================
|
||||
|
||||
{% include "t.html" with a=1 %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(include
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string))))
|
||||
variable: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include With Several Bindings
|
||||
==================
|
||||
|
||||
{% include "t.html" with a=1 b=2 %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(include
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string))))
|
||||
variable: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number))))
|
||||
variable: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include With Context And Only
|
||||
==================
|
||||
|
||||
{% include "t.html" with a=1 only %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(include
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string))))
|
||||
variable: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include With Only Before With
|
||||
==================
|
||||
|
||||
{% include "t.html" only with a=1 %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(include
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string))))
|
||||
variable: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include With A Repeated Binding
|
||||
==================
|
||||
|
||||
{% include "t.html" with a=1 a=2 %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(include
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string))))
|
||||
variable: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number))))
|
||||
variable: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Include Without A Name
|
||||
:error
|
||||
==================
|
||||
|
||||
{% include %}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Include With Nothing To Bind
|
||||
:error
|
||||
==================
|
||||
|
||||
{% include "t.html" with %}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Include With With Twice
|
||||
:error
|
||||
==================
|
||||
|
||||
{% include "t.html" with a=1 with b=2 %}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Include With Only Twice
|
||||
:error
|
||||
==================
|
||||
|
||||
{% include "t.html" only only %}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Include With An Unknown Option
|
||||
:error
|
||||
==================
|
||||
|
||||
{% include "t.html" bogus %}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Include With A Legacy Binding
|
||||
:error
|
||||
==================
|
||||
|
||||
{% include "t.html" with a as b %}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Include With A Second Name
|
||||
:error
|
||||
==================
|
||||
|
||||
{% include "t.html" "u.html" %}
|
||||
|
||||
---
|
||||
Reference in new issue
Block a user