add support for custom tags and filters
This commit is contained in:
1 parent
10e52ace5d
commit
eb81b73104
7 files changed
+29103
-28660
No files matched your search
@@ -78,6 +78,23 @@ Django parses everything between `{{` and `}}` — and the entire remainder of `
|
||||
whitespace first, so a pipe there must be tight. Hence `_filtered_value_spaced` /
|
||||
`_filter_expression_spaced`, aliased back to the plain node names so the tree shape stays identical.
|
||||
|
||||
### Names a `{% load %}` brought in
|
||||
|
||||
A library's tags and filters are registered in Python, so the grammar cannot know their names, their
|
||||
arity, or whether a tag is a block tag. Two fallback rules accept them:
|
||||
|
||||
- `custom_tag` — `simpleTag($, $.identifier)`, i.e. what `simple_tag`/`inclusion_tag` accept, which is how
|
||||
a tag is registered unless it needs the parser itself.
|
||||
- the last alternative of `filter`, whose name is `$.identifier` rather than one of the builtin literals.
|
||||
|
||||
**Builtin names must stay keyword-extractable, or the fallbacks swallow them.** `word: $.identifier` turns
|
||||
each builtin's name into its own token, which the lexer prefers wherever it is valid, so a builtin commits
|
||||
to its own alternative and its argument rules still apply. This is why a filter's name and its `:` are
|
||||
separate tokens: while the name was spelled `"add:"` it was not word-shaped, so a bare `add` lexed as an
|
||||
identifier and reached the fallback, losing the arity check for all 20 filters that require an argument.
|
||||
`FILTERS_WITHOUT_ARGUMENT` / `FILTERS_WITH_ARGUMENT` / `FILTERS_WITH_OPTIONAL_ARGUMENT` carry that arity,
|
||||
which Django itself enforces while it parses the template ("add requires 2 arguments, 1 provided").
|
||||
|
||||
### External scanner (`src/scanner.c`)
|
||||
|
||||
Nine external tokens, for the constraints a context-free grammar cannot express:
|
||||
@@ -99,7 +116,8 @@ do not, and belong in a linter instead.
|
||||
### Queries
|
||||
|
||||
`queries/highlights.scm` lists tag and filter names explicitly, so adding either to the grammar means
|
||||
adding it there too. `queries/locals.scm` relies on the `variable:` field to tell a binding from a
|
||||
adding it there too; filter names appear there without their colon. A name the grammar does not know is
|
||||
captured through its field instead (`(filter name: (identifier))`, `(custom_tag tag: (identifier))`). `queries/locals.scm` relies on the `variable:` field to tell a binding from a
|
||||
reference — another reason to keep `asVariable` uniform.
|
||||
|
||||
## Testing
|
||||
@@ -137,5 +155,14 @@ documentation or memory. Both checks are worth repeating whenever tags, filters
|
||||
- `{% querystring page=2 page=3 %}` (a repeated `**kwargs` key) is a Django error but is not expressible in
|
||||
a context-free grammar. Repeats _are_ rejected wherever the signature names its arguments.
|
||||
- `{% csp_nonce_attr "a" media="b" %}` is accepted, matching Django, which only rejects it at render time.
|
||||
- A misspelled tag or filter cannot be caught: `{{ x|lenght }}` is indistinguishable from a filter some
|
||||
library registered. Cross-referencing names against `{% load %}` needs the project's Python, so it
|
||||
belongs in a linter; the `load` rule already parses the library and `from` names for one to use.
|
||||
- `{% mytag %}…{% endmytag %}` parses as two sibling `custom_tag`s. Nesting them would mean guessing that
|
||||
an unknown tag is a block tag.
|
||||
- A custom tag's contents are only assumed to be the `simple_tag` shape. `@register.tag` receives the raw
|
||||
token and may parse anything, so `{% mytag <<>> %}` is rejected here and not by Django.
|
||||
- A library may override a builtin (`Parser.add_library` is `self.filters.update(...)`), so a project that
|
||||
redefines `length` with a different arity gets a false error here.
|
||||
- `partial`/`partialdef` are Django builtins as of Django 6; `elif`/`else`/`empty` are modelled as parts of
|
||||
their enclosing tag rather than as separate tags.
|
||||
+104
-59
@@ -38,7 +38,7 @@ function part(first, ...rest) {
|
||||
|
||||
/**
|
||||
* A tag, which may hug its delimiters ("{%cycle 1%}") or not.
|
||||
* @param {string} tag
|
||||
* @param {RuleOrLiteral} tag
|
||||
* @param {...RuleOrLiteral} args
|
||||
* @returns {SeqRule}
|
||||
*/
|
||||
@@ -121,7 +121,7 @@ function arrangements(items) {
|
||||
* @param {boolean|Record<string, RuleOrLiteral>} kwargs true for any
|
||||
* "name=value" pair (**kwargs), false for none, or the accepted names mapped
|
||||
* to their value rules, each of which may be given at most once
|
||||
* @param {string} tag
|
||||
* @param {RuleOrLiteral} tag
|
||||
* @returns {SeqRule}
|
||||
*/
|
||||
function simpleTag($, tag, args = true, kwargs = true) {
|
||||
@@ -148,6 +148,79 @@ function simpleTag($, tag, args = true, kwargs = true) {
|
||||
return block(tag, ...parts, optional(asVariable($)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Django checks a filter's argument count against the registered function
|
||||
* while it parses the template, so the arity of a builtin is syntax here:
|
||||
* "length:2" and a bare "add" are both errors.
|
||||
*/
|
||||
const FILTERS_WITHOUT_ARGUMENT = [
|
||||
"addslashes",
|
||||
"capfirst",
|
||||
"escape",
|
||||
"escapejs",
|
||||
"escapeseq",
|
||||
"filesizeformat",
|
||||
"first",
|
||||
"force_escape",
|
||||
"iriencode",
|
||||
"last",
|
||||
"length",
|
||||
"linebreaks",
|
||||
"linebreaksbr",
|
||||
"linenumbers",
|
||||
"lower",
|
||||
"make_list",
|
||||
"phone2numeric",
|
||||
"pprint",
|
||||
"random",
|
||||
"safe",
|
||||
"safeseq",
|
||||
"slugify",
|
||||
"striptags",
|
||||
"title",
|
||||
"unordered_list",
|
||||
"upper",
|
||||
"urlize",
|
||||
"wordcount",
|
||||
];
|
||||
|
||||
/** Builtin filters that require an argument. */
|
||||
const FILTERS_WITH_ARGUMENT = [
|
||||
"add",
|
||||
"center",
|
||||
"cut",
|
||||
"default",
|
||||
"default_if_none",
|
||||
"dictsort",
|
||||
"dictsortreversed",
|
||||
"divisibleby",
|
||||
"get_digit",
|
||||
"join",
|
||||
"ljust",
|
||||
"rjust",
|
||||
"slice",
|
||||
"stringformat",
|
||||
"truncatechars",
|
||||
"truncatechars_html",
|
||||
"truncatewords",
|
||||
"truncatewords_html",
|
||||
"urlizetrunc",
|
||||
"wordwrap",
|
||||
];
|
||||
|
||||
/** Builtin filters that take an argument or no argument. */
|
||||
const FILTERS_WITH_OPTIONAL_ARGUMENT = [
|
||||
"date",
|
||||
"floatformat",
|
||||
"json_script",
|
||||
"pluralize",
|
||||
"time",
|
||||
"timesince",
|
||||
"timeuntil",
|
||||
"urlencode",
|
||||
"yesno",
|
||||
];
|
||||
|
||||
/** Django's string constant, which takes any escape but a line break. */
|
||||
const STRING = /"(?:[^"\\]|\\[^\n])*"|'(?:[^'\\]|\\[^\n])*'/;
|
||||
|
||||
@@ -267,6 +340,7 @@ const django = grammar({
|
||||
$.comment_group,
|
||||
$.csp_nonce_attr,
|
||||
$.csrf_token,
|
||||
$.custom_tag,
|
||||
$.cycle,
|
||||
$.debug,
|
||||
$.extends,
|
||||
@@ -291,65 +365,30 @@ const django = grammar({
|
||||
$.width_ratio,
|
||||
$.with_group,
|
||||
),
|
||||
/**
|
||||
* A filter is a name and, after a colon, at most one argument. The name is
|
||||
* a token of its own rather than part of a "name:" token so that Django's
|
||||
* builtins are keyword-extracted: a builtin written with the wrong arity
|
||||
* then cannot be read as a filter from a loaded library instead.
|
||||
*/
|
||||
filter: ($) =>
|
||||
choice(
|
||||
seq("add:", $.value),
|
||||
"addslashes",
|
||||
"capfirst",
|
||||
seq("center:", $.value),
|
||||
seq("cut:", $.value),
|
||||
choice(seq("date:", $.value), "date"),
|
||||
seq("default:", $.value),
|
||||
seq("default_if_none:", $.value),
|
||||
seq("dictsort:", $.value),
|
||||
seq("dictsortreversed:", $.value),
|
||||
seq("divisibleby:", $.value),
|
||||
"escape",
|
||||
"escapejs",
|
||||
"escapeseq",
|
||||
"filesizeformat",
|
||||
"first",
|
||||
choice(seq("floatformat:", $.value), "floatformat"),
|
||||
"force_escape",
|
||||
seq("get_digit:", $.value),
|
||||
"iriencode",
|
||||
seq("join:", $.value),
|
||||
choice(seq("json_script:", $.value), "json_script"),
|
||||
"last",
|
||||
"length",
|
||||
"linebreaks",
|
||||
"linebreaksbr",
|
||||
"linenumbers",
|
||||
seq("ljust:", $.value),
|
||||
"lower",
|
||||
"make_list",
|
||||
"phone2numeric",
|
||||
choice(seq("pluralize:", $.value), "pluralize"),
|
||||
"pprint",
|
||||
"random",
|
||||
seq("rjust:", $.value),
|
||||
"safe",
|
||||
"safeseq",
|
||||
seq("slice:", $.value),
|
||||
"slugify",
|
||||
seq("stringformat:", $.value),
|
||||
"striptags",
|
||||
choice(seq("time:", $.value), "time"),
|
||||
choice(seq("timesince:", $.value), "timesince"),
|
||||
choice(seq("timeuntil:", $.value), "timeuntil"),
|
||||
"title",
|
||||
seq("truncatechars:", $.value),
|
||||
seq("truncatechars_html:", $.value),
|
||||
seq("truncatewords:", $.value),
|
||||
seq("truncatewords_html:", $.value),
|
||||
"unordered_list",
|
||||
"upper",
|
||||
choice(seq("urlencode:", $.value), "urlencode"),
|
||||
"urlize",
|
||||
seq("urlizetrunc:", $.value),
|
||||
"wordcount",
|
||||
seq("wordwrap:", $.value),
|
||||
choice(seq("yesno:", $.value), "yesno"),
|
||||
field("name", choice(...FILTERS_WITHOUT_ARGUMENT)),
|
||||
seq(
|
||||
field("name", choice(...FILTERS_WITH_ARGUMENT)),
|
||||
":",
|
||||
field("argument", $.value),
|
||||
),
|
||||
seq(
|
||||
field("name", choice(...FILTERS_WITH_OPTIONAL_ARGUMENT)),
|
||||
optional(seq(":", field("argument", $.value))),
|
||||
),
|
||||
// a filter a "load" brought in: its name is not known here, and so
|
||||
// neither is whether it takes an argument
|
||||
seq(
|
||||
field("name", $.identifier),
|
||||
optional(seq(":", field("argument", $.value))),
|
||||
),
|
||||
),
|
||||
autoescape_group: ($) =>
|
||||
seq(
|
||||
@@ -374,6 +413,12 @@ const django = grammar({
|
||||
csp_nonce_attr: ($) =>
|
||||
simpleTag($, "csp_nonce_attr", 1, { media: $.filtered_value }),
|
||||
csrf_token: ($) => block("csrf_token"),
|
||||
/**
|
||||
* A tag a "load" brought in. Its arguments cannot be known here, so what
|
||||
* is accepted is what Library.simple_tag and Library.inclusion_tag take,
|
||||
* which is how a tag is registered unless it needs the parser itself.
|
||||
*/
|
||||
custom_tag: ($) => simpleTag($, $.identifier),
|
||||
cycle: ($) =>
|
||||
block(
|
||||
"cycle",
|
||||
|
||||
+31
-32
@@ -25,6 +25,7 @@ variable: (identifier) @variable.parameter
|
||||
("in")
|
||||
("=")
|
||||
("|")
|
||||
(":")
|
||||
(".")] @operator
|
||||
|
||||
[
|
||||
@@ -90,74 +91,72 @@ tag: [
|
||||
("with")
|
||||
("endwith")] @function
|
||||
|
||||
(filter .
|
||||
[
|
||||
("add:")
|
||||
(filter
|
||||
name: [
|
||||
("add")
|
||||
("addslashes")
|
||||
("capfirst")
|
||||
("center:")
|
||||
("cut:")
|
||||
("center")
|
||||
("cut")
|
||||
("date")
|
||||
("date:")
|
||||
("default:")
|
||||
("default_if_none:")
|
||||
("dictsort:")
|
||||
("dictsortreversed:")
|
||||
("divisibleby:")
|
||||
("default")
|
||||
("default_if_none")
|
||||
("dictsort")
|
||||
("dictsortreversed")
|
||||
("divisibleby")
|
||||
("escape")
|
||||
("escapejs")
|
||||
("escapeseq")
|
||||
("filesizeformat")
|
||||
("first")
|
||||
("floatformat")
|
||||
("floatformat:")
|
||||
("force_escape")
|
||||
("get_digit:")
|
||||
("get_digit")
|
||||
("iriencode")
|
||||
("join:")
|
||||
("join")
|
||||
("json_script")
|
||||
("json_script:")
|
||||
("last")
|
||||
("length")
|
||||
("linebreaks")
|
||||
("linebreaksbr")
|
||||
("linenumbers")
|
||||
("ljust:")
|
||||
("ljust")
|
||||
("lower")
|
||||
("make_list")
|
||||
("phone2numeric")
|
||||
("pluralize")
|
||||
("pluralize:")
|
||||
("pprint")
|
||||
("random")
|
||||
("rjust:")
|
||||
("rjust")
|
||||
("safe")
|
||||
("safeseq")
|
||||
("slice:")
|
||||
("slice")
|
||||
("slugify")
|
||||
("stringformat:")
|
||||
("stringformat")
|
||||
("striptags")
|
||||
("time")
|
||||
("time:")
|
||||
("timesince")
|
||||
("timesince:")
|
||||
("timeuntil")
|
||||
("timeuntil:")
|
||||
("title")
|
||||
("truncatechars:")
|
||||
("truncatechars_html:")
|
||||
("truncatewords:")
|
||||
("truncatewords_html:")
|
||||
("truncatechars")
|
||||
("truncatechars_html")
|
||||
("truncatewords")
|
||||
("truncatewords_html")
|
||||
("unordered_list")
|
||||
("upper")
|
||||
("urlencode")
|
||||
("urlencode:")
|
||||
("urlize")
|
||||
("urlizetrunc:")
|
||||
("urlizetrunc")
|
||||
("wordcount")
|
||||
("wordwrap:")
|
||||
("yesno")
|
||||
("yesno:")] @function)
|
||||
("wordwrap")
|
||||
("yesno")] @function)
|
||||
|
||||
; a filter or tag a "load" brought in, whose name the grammar does not know
|
||||
(filter
|
||||
name: (identifier) @function.call)
|
||||
|
||||
(custom_tag
|
||||
tag: (identifier) @function.call)
|
||||
|
||||
(load
|
||||
(identifier) @function)
|
||||
+346
-430
@@ -554,6 +554,10 @@
|
||||
"type": "SYMBOL",
|
||||
"name": "csrf_token"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "custom_tag"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "cycle"
|
||||
@@ -652,18 +656,11 @@
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"type": "FIELD",
|
||||
"name": "name",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "add:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "addslashes"
|
||||
@@ -672,119 +669,6 @@
|
||||
"type": "STRING",
|
||||
"value": "capfirst"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "center:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "cut:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "date:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "date"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "default:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "default_if_none:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "dictsort:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "dictsortreversed:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "divisibleby:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "escape"
|
||||
@@ -805,84 +689,14 @@
|
||||
"type": "STRING",
|
||||
"value": "first"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "floatformat:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "floatformat"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "force_escape"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "get_digit:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "iriencode"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "join:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "json_script:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "json_script"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "last"
|
||||
@@ -903,19 +717,6 @@
|
||||
"type": "STRING",
|
||||
"value": "linenumbers"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "ljust:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "lower"
|
||||
@@ -928,28 +729,6 @@
|
||||
"type": "STRING",
|
||||
"value": "phone2numeric"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "pluralize:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "pluralize"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "pprint"
|
||||
@@ -958,19 +737,6 @@
|
||||
"type": "STRING",
|
||||
"value": "random"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "rjust:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "safe"
|
||||
@@ -979,162 +745,18 @@
|
||||
"type": "STRING",
|
||||
"value": "safeseq"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "slice:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "slugify"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "stringformat:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "striptags"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "time:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "time"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "timesince:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "timesince"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "timeuntil:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "timeuntil"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "title"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatechars:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatechars_html:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatewords:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatewords_html:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "unordered_list"
|
||||
@@ -1143,62 +765,171 @@
|
||||
"type": "STRING",
|
||||
"value": "upper"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "urlencode:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "urlencode"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "urlize"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "urlizetrunc:"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "wordcount"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "name",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "wordwrap:"
|
||||
"value": "add"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "center"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "cut"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "default"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "default_if_none"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "dictsort"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "dictsortreversed"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "divisibleby"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "get_digit"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "join"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "ljust"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "rjust"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "slice"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "stringformat"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatechars"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatechars_html"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatewords"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "truncatewords_html"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "urlizetrunc"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "wordwrap"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "argument",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "name",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "date"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "floatformat"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "json_script"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "pluralize"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "time"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "timesince"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "timeuntil"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "urlencode"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "yesno"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
@@ -1207,17 +938,60 @@
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "yesno:"
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "argument",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "name",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "yesno"
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "argument",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "value"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1782,6 +1556,134 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"custom_tag": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{%"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "tag",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "filtered_value"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "="
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "filtered_value"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "as"
|
||||
},
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "variable",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[ \\t\\r\\n]+"
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "%}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cycle": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
@@ -4555,11 +4457,22 @@
|
||||
},
|
||||
"extras": [],
|
||||
"conflicts": [
|
||||
["template"],
|
||||
["predicate"],
|
||||
["library", "load"],
|
||||
["_filtered_value_spaced"],
|
||||
["_filter_expression_spaced"]
|
||||
[
|
||||
"template"
|
||||
],
|
||||
[
|
||||
"predicate"
|
||||
],
|
||||
[
|
||||
"library",
|
||||
"load"
|
||||
],
|
||||
[
|
||||
"_filtered_value_spaced"
|
||||
],
|
||||
[
|
||||
"_filter_expression_spaced"
|
||||
]
|
||||
],
|
||||
"precedences": [],
|
||||
"externals": [
|
||||
@@ -4601,7 +4514,10 @@
|
||||
}
|
||||
],
|
||||
"inline": [],
|
||||
"supertypes": ["template_tag", "template_block_groups"],
|
||||
"supertypes": [
|
||||
"template_tag",
|
||||
"template_block_groups"
|
||||
],
|
||||
"reserved": {
|
||||
"global": [
|
||||
{
|
||||
|
||||
+309
-58
@@ -23,6 +23,10 @@
|
||||
"type": "csrf_token",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "custom_tag",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "cycle",
|
||||
"named": true
|
||||
@@ -300,6 +304,46 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "custom_tag",
|
||||
"named": true,
|
||||
"fields": {
|
||||
"tag": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"variable": {
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "filtered_value",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "cycle",
|
||||
"named": true,
|
||||
@@ -381,8 +425,8 @@
|
||||
{
|
||||
"type": "filter",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"fields": {
|
||||
"argument": {
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"types": [
|
||||
@@ -391,6 +435,245 @@
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "add",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "addslashes",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "capfirst",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "center",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "cut",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "date",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "default",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "default_if_none",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "dictsort",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "dictsortreversed",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "divisibleby",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "escape",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "escapejs",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "escapeseq",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "filesizeformat",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "first",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "floatformat",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "force_escape",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "get_digit",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "identifier",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "iriencode",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "join",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "json_script",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "last",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "length",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "linebreaks",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "linebreaksbr",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "linenumbers",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "ljust",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "lower",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "make_list",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "phone2numeric",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "pluralize",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "pprint",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "random",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "rjust",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "safe",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "safeseq",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "slice",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "slugify",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "stringformat",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "striptags",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "time",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "timesince",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "timeuntil",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatechars",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatechars_html",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatewords",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatewords_html",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "unordered_list",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "upper",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "urlencode",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "urlize",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "urlizetrunc",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "wordcount",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "wordwrap",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "yesno",
|
||||
"named": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1317,6 +1600,10 @@
|
||||
"type": ".",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": ":",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "<",
|
||||
"named": false
|
||||
@@ -1346,7 +1633,7 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "add:",
|
||||
"type": "add",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1386,7 +1673,7 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "center:",
|
||||
"type": "center",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1426,7 +1713,7 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "cut:",
|
||||
"type": "cut",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1437,32 +1724,28 @@
|
||||
"type": "date",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "date:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "debug",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "default:",
|
||||
"type": "default",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "default_if_none:",
|
||||
"type": "default_if_none",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "dictsort:",
|
||||
"type": "dictsort",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "dictsortreversed:",
|
||||
"type": "dictsortreversed",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "divisibleby:",
|
||||
"type": "divisibleby",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1557,10 +1840,6 @@
|
||||
"type": "floatformat",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "floatformat:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "for",
|
||||
"named": false
|
||||
@@ -1574,7 +1853,7 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "get_digit:",
|
||||
"type": "get_digit",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1610,17 +1889,13 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "join:",
|
||||
"type": "join",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "json_script",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "json_script:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "last",
|
||||
"named": false
|
||||
@@ -1642,7 +1917,7 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "ljust:",
|
||||
"type": "ljust",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1725,10 +2000,6 @@
|
||||
"type": "pluralize",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "pluralize:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "pop_block",
|
||||
"named": true
|
||||
@@ -1774,7 +2045,7 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "rjust:",
|
||||
"type": "rjust",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1790,7 +2061,7 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "slice:",
|
||||
"type": "slice",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1806,7 +2077,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "stringformat:",
|
||||
"type": "stringformat",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1821,44 +2092,32 @@
|
||||
"type": "time",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "time:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "timesince",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "timesince:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "timeuntil",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "timeuntil:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatechars:",
|
||||
"type": "truncatechars",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatechars_html:",
|
||||
"type": "truncatechars_html",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatewords:",
|
||||
"type": "truncatewords",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "truncatewords_html:",
|
||||
"type": "truncatewords_html",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1877,16 +2136,12 @@
|
||||
"type": "urlencode",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "urlencode:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "urlize",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "urlizetrunc:",
|
||||
"type": "urlizetrunc",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
@@ -1914,17 +2169,13 @@
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "wordwrap:",
|
||||
"type": "wordwrap",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "yesno",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "yesno:",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "{#",
|
||||
"named": false
|
||||
|
||||
+28054
-28080
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,231 @@
|
||||
==================
|
||||
Custom Tag
|
||||
==================
|
||||
|
||||
{% mytag %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(custom_tag
|
||||
tag: (identifier))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Tag With Arguments
|
||||
==================
|
||||
|
||||
{% mytag a "b" 3 %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(custom_tag
|
||||
tag: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier))))
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(string))))
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Tag With Keyword Arguments
|
||||
==================
|
||||
|
||||
{% mytag a b=1 %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(custom_tag
|
||||
tag: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier))))
|
||||
(identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Tag With As
|
||||
==================
|
||||
|
||||
{% mytag a as result %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(custom_tag
|
||||
tag: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier))))
|
||||
variable: (identifier))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Tag With Filtered Argument
|
||||
==================
|
||||
|
||||
{% mytag a|upper %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(custom_tag
|
||||
tag: (identifier)
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier)))
|
||||
(filter_expression
|
||||
(filter))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Tag Does Not Nest
|
||||
==================
|
||||
|
||||
{% mytag %}hi{% endmytag %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(custom_tag
|
||||
tag: (identifier))
|
||||
(content)
|
||||
(custom_tag
|
||||
tag: (identifier))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Tag Does Not Cover A Builtin Name
|
||||
:error
|
||||
==================
|
||||
|
||||
{% cycle %}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Custom Filter
|
||||
==================
|
||||
|
||||
{{ x|intcomma }}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(template_variable
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier)))
|
||||
(filter_expression
|
||||
(filter
|
||||
name: (identifier)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Filter With Argument
|
||||
==================
|
||||
|
||||
{{ x|naturaltime:"y" }}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(template_variable
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier)))
|
||||
(filter_expression
|
||||
(filter
|
||||
name: (identifier)
|
||||
argument: (value
|
||||
(literal
|
||||
(string)))))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Filter In A Chain With A Builtin
|
||||
==================
|
||||
|
||||
{{ x|intcomma|upper }}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(template_variable
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier)))
|
||||
(filter_expression
|
||||
(filter
|
||||
name: (identifier))
|
||||
(filter))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Custom Filter In A Tag
|
||||
==================
|
||||
|
||||
{% firstof a|intcomma %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(firstof
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier)))
|
||||
(filter_expression
|
||||
(filter
|
||||
name: (identifier)))))
|
||||
(content))
|
||||
|
||||
==================
|
||||
Builtin Filter Without Its Required Argument
|
||||
:error
|
||||
==================
|
||||
|
||||
{{ x|add }}
|
||||
|
||||
---
|
||||
|
||||
|
||||
==================
|
||||
Builtin Filter With An Argument It Does Not Take
|
||||
:error
|
||||
==================
|
||||
|
||||
{{ x|length:2 }}
|
||||
|
||||
---
|
||||
Reference in new issue
Block a user