add static
This commit is contained in:
1 parent
eb81b73104
commit
c0e7b4697d
8 files changed
+24033
-21222
No files matched your search
@@ -95,6 +95,28 @@ identifier and reached the fallback, losing the arity check for all 20 filters t
|
|||||||
`FILTERS_WITHOUT_ARGUMENT` / `FILTERS_WITH_ARGUMENT` / `FILTERS_WITH_OPTIONAL_ARGUMENT` carry that arity,
|
`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").
|
which Django itself enforces while it parses the template ("add requires 2 arguments, 1 provided").
|
||||||
|
|
||||||
|
### First-party libraries
|
||||||
|
|
||||||
|
Django ships `i18n`, `l10n`, `static`, `cache` and `tz` as libraries rather than builtins. Their tags are
|
||||||
|
modelled as ordinary tags (so far: `static`), and the grammar **never requires the `{% load %}`**, because
|
||||||
|
an engine can preload a library through `OPTIONS: {"builtins": [...]}`, which makes `{% static "a" %}` valid
|
||||||
|
with no load at all.
|
||||||
|
|
||||||
|
Whether a load is present is a question about the order of nodes, not about how the template parses, so it
|
||||||
|
belongs in a tool. `queries/libraries.scm` supplies the halves — `@library.<name>` on each tag, and
|
||||||
|
`@load.library` / `@load.name` on the loads — and the tool does the join, because tree-sitter queries have
|
||||||
|
no ordering predicate to express it. What such a tool needs to know about Django's behaviour:
|
||||||
|
|
||||||
|
- Loading is **positional**: `{% trans "x" %}{% load i18n %}` is an error, because the parser adds to its
|
||||||
|
tag dict as it walks tokens.
|
||||||
|
- Loading is **per file**: a `{% load %}` does not reach a template that `{% extends %}` or `{% include %}`
|
||||||
|
this one.
|
||||||
|
- `{% load trans from i18n %}` makes only `trans` available, not the rest of the library.
|
||||||
|
|
||||||
|
Modelling a library name makes it keyword-extracted, so it no longer reaches `custom_tag`. A project that
|
||||||
|
registers its own tag under one of these names and a different signature therefore gets a parse error. That
|
||||||
|
is accepted: these names are common enough that shadowing them is the mistake.
|
||||||
|
|
||||||
### External scanner (`src/scanner.c`)
|
### External scanner (`src/scanner.c`)
|
||||||
|
|
||||||
Nine external tokens, for the constraints a context-free grammar cannot express:
|
Nine external tokens, for the constraints a context-free grammar cannot express:
|
||||||
@@ -117,7 +139,8 @@ do not, and belong in a linter instead.
|
|||||||
|
|
||||||
`queries/highlights.scm` lists tag and filter names explicitly, so adding either to the grammar means
|
`queries/highlights.scm` lists tag and filter names explicitly, so adding either to the grammar means
|
||||||
adding it there too; filter names appear there without their colon. A name the grammar does not know is
|
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
|
captured through its field instead (`(filter name: (identifier))`, `(custom_tag tag: (identifier))`). `queries/libraries.scm` is not a query editors run themselves; it is data for a linter, and every tag
|
||||||
|
or filter added from a library belongs in it. `queries/locals.scm` relies on the `variable:` field to tell a binding from a
|
||||||
reference — another reason to keep `asVariable` uniform.
|
reference — another reason to keep `asVariable` uniform.
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
@@ -141,6 +164,9 @@ documentation or memory. Both checks are worth repeating whenever tags, filters
|
|||||||
`register.filters` against `grammar.js`. For filters also compare argument arity via
|
`register.filters` against `grammar.js`. For filters also compare argument arity via
|
||||||
`inspect.signature`, ignoring the framework-injected `autoescape` parameter, which is never written in a
|
`inspect.signature`, ignoring the framework-injected `autoescape` parameter, which is never written in a
|
||||||
template. Note `querystring` and `csp_nonce_attr` register as `simple_tag`, not `@register.tag`.
|
template. Note `querystring` and `csp_nonce_attr` register as `simple_tag`, not `@register.tag`.
|
||||||
|
- **Library contents** — `django.templatetags.<name>.register` gives a library's `tags` and `filters`.
|
||||||
|
All of them are registered with `@register.tag`, so `inspect.signature` only reports `(parser, token)`
|
||||||
|
and a signature has to come from the differential below or from reading the compile function.
|
||||||
- **Syntax differential** — run candidate snippets through `django.template.Template()` and through
|
- **Syntax differential** — run candidate snippets through `django.template.Template()` and through
|
||||||
`tree-sitter parse`, and compare accept/reject. This is how the `simple_tag` argument rules, the `_()`
|
`tree-sitter parse`, and compare accept/reject. This is how the `simple_tag` argument rules, the `_()`
|
||||||
literal, and the filter-pipe spacing were pinned down.
|
literal, and the filter-pipe spacing were pinned down.
|
||||||
@@ -164,5 +190,9 @@ documentation or memory. Both checks are worth repeating whenever tags, filters
|
|||||||
token and may parse anything, so `{% mytag <<>> %}` is rejected here and not by Django.
|
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
|
- 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.
|
redefines `length` with a different arity gets a false error here.
|
||||||
|
- Django's `static` tags ignore what follows their argument: `StaticNode.handle_token` looks for `as` two
|
||||||
|
bits from the end, so `{% static "a" junk %}` and `{% static "a" as u v %}` are accepted there and
|
||||||
|
rejected here, and `PrefixNode.handle_token` raises `IndexError` rather than `TemplateSyntaxError` on
|
||||||
|
`{% get_static_prefix as %}`.
|
||||||
- `partial`/`partialdef` are Django builtins as of Django 6; `elif`/`else`/`empty` are modelled as parts of
|
- `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.
|
their enclosing tag rather than as separate tags.
|
||||||
@@ -347,6 +347,8 @@ const django = grammar({
|
|||||||
$.filter_group,
|
$.filter_group,
|
||||||
$.firstof,
|
$.firstof,
|
||||||
$.for_group,
|
$.for_group,
|
||||||
|
$.get_media_prefix,
|
||||||
|
$.get_static_prefix,
|
||||||
$.if_group,
|
$.if_group,
|
||||||
$.ifchanged_group,
|
$.ifchanged_group,
|
||||||
$.include,
|
$.include,
|
||||||
@@ -359,6 +361,7 @@ const django = grammar({
|
|||||||
$.regroup,
|
$.regroup,
|
||||||
$.reset_cycle,
|
$.reset_cycle,
|
||||||
$.spaceless_group,
|
$.spaceless_group,
|
||||||
|
$.static,
|
||||||
$.template_tag_block,
|
$.template_tag_block,
|
||||||
$.url_block,
|
$.url_block,
|
||||||
$.verbatim_group,
|
$.verbatim_group,
|
||||||
@@ -477,6 +480,9 @@ const django = grammar({
|
|||||||
optional(seq(block("empty"), optional($.template))),
|
optional(seq(block("empty"), optional($.template))),
|
||||||
block("endfor"),
|
block("endfor"),
|
||||||
),
|
),
|
||||||
|
get_media_prefix: ($) => block("get_media_prefix", optional(asVariable($))),
|
||||||
|
get_static_prefix: ($) =>
|
||||||
|
block("get_static_prefix", optional(asVariable($))),
|
||||||
if_group: ($) =>
|
if_group: ($) =>
|
||||||
seq(
|
seq(
|
||||||
block("if", part($.predicate)),
|
block("if", part($.predicate)),
|
||||||
@@ -529,6 +535,8 @@ const django = grammar({
|
|||||||
reset_cycle: ($) => block("resetcycle", optional(part($.identifier))),
|
reset_cycle: ($) => block("resetcycle", optional(part($.identifier))),
|
||||||
spaceless_group: ($) =>
|
spaceless_group: ($) =>
|
||||||
seq(block("spaceless"), optional($.template), block("endspaceless")),
|
seq(block("spaceless"), optional($.template), block("endspaceless")),
|
||||||
|
static: ($) =>
|
||||||
|
block("static", part($.filtered_value), optional(asVariable($))),
|
||||||
template_tag_block: ($) =>
|
template_tag_block: ($) =>
|
||||||
block(
|
block(
|
||||||
"templatetag",
|
"templatetag",
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ tag: [
|
|||||||
("for")
|
("for")
|
||||||
("empty")
|
("empty")
|
||||||
("endfor")
|
("endfor")
|
||||||
|
("get_media_prefix")
|
||||||
|
("get_static_prefix")
|
||||||
("if")
|
("if")
|
||||||
("elif")
|
("elif")
|
||||||
("else")
|
("else")
|
||||||
@@ -84,6 +86,7 @@ tag: [
|
|||||||
("resetcycle")
|
("resetcycle")
|
||||||
("spaceless")
|
("spaceless")
|
||||||
("endspaceless")
|
("endspaceless")
|
||||||
|
("static")
|
||||||
("templatetag")
|
("templatetag")
|
||||||
("url")
|
("url")
|
||||||
("verbatim")
|
("verbatim")
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
; Which library a tag or filter is registered in.
|
||||||
|
;
|
||||||
|
; The grammar accepts these whether or not a "{% load %}" precedes them: an
|
||||||
|
; engine may preload a library through its "builtins" option, and Django
|
||||||
|
; resolves a name against the libraries loaded *so far*, which is a question
|
||||||
|
; about the order of nodes rather than about how the template parses. A tool
|
||||||
|
; that wants to report a missing load can run this query and compare positions
|
||||||
|
; itself, and should skip the check for a library the engine preloads.
|
||||||
|
;
|
||||||
|
; Loading is per file and positional: "{% load %}" does not reach a template
|
||||||
|
; that extends or includes this one, and a tag written before the load is an
|
||||||
|
; error even though the load is in the same file.
|
||||||
|
|
||||||
|
[
|
||||||
|
(static)
|
||||||
|
(get_static_prefix)
|
||||||
|
(get_media_prefix)] @library.static
|
||||||
|
|
||||||
|
; "{% load static %}" makes every name in the library available; "{% load
|
||||||
|
; static from staticfiles %}" makes only the names listed available.
|
||||||
|
(load
|
||||||
|
(library) @load.library)
|
||||||
|
|
||||||
|
(load
|
||||||
|
(identifier) @load.name)
|
||||||
@@ -582,6 +582,14 @@
|
|||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "for_group"
|
"name": "for_group"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "get_media_prefix"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "get_static_prefix"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "if_group"
|
"name": "if_group"
|
||||||
@@ -630,6 +638,10 @@
|
|||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "spaceless_group"
|
"name": "spaceless_group"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "static"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "template_tag_block"
|
"name": "template_tag_block"
|
||||||
@@ -2413,6 +2425,172 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"get_media_prefix": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "{%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "[ \\t\\r\\n]+"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "FIELD",
|
||||||
|
"name": "tag",
|
||||||
|
"content": {
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "get_media_prefix"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": "%}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"get_static_prefix": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "{%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "[ \\t\\r\\n]+"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "FIELD",
|
||||||
|
"name": "tag",
|
||||||
|
"content": {
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "get_static_prefix"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": "%}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"if_group": {
|
"if_group": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
@@ -3823,6 +4001,102 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"static": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "{%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "[ \\t\\r\\n]+"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "FIELD",
|
||||||
|
"name": "tag",
|
||||||
|
"content": {
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "static"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "[ \\t\\r\\n]+"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": "%}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"template_tag_block": {
|
"template_tag_block": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
|
|||||||
@@ -51,6 +51,14 @@
|
|||||||
"type": "for_group",
|
"type": "for_group",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get_media_prefix",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "get_static_prefix",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "if_group",
|
"type": "if_group",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -99,6 +107,10 @@
|
|||||||
"type": "spaceless_group",
|
"type": "spaceless_group",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "static",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "template_tag_block",
|
"type": "template_tag_block",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -854,6 +866,58 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get_media_prefix",
|
||||||
|
"named": true,
|
||||||
|
"fields": {
|
||||||
|
"tag": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "get_media_prefix",
|
||||||
|
"named": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"variable": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": false,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "identifier",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "get_static_prefix",
|
||||||
|
"named": true,
|
||||||
|
"fields": {
|
||||||
|
"tag": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "get_static_prefix",
|
||||||
|
"named": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"variable": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": false,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "identifier",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "if_group",
|
"type": "if_group",
|
||||||
"named": true,
|
"named": true,
|
||||||
@@ -1305,6 +1369,42 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "static",
|
||||||
|
"named": true,
|
||||||
|
"fields": {
|
||||||
|
"tag": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "static",
|
||||||
|
"named": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"variable": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": false,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "identifier",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "filtered_value",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "template",
|
"type": "template",
|
||||||
"named": true,
|
"named": true,
|
||||||
@@ -1856,6 +1956,14 @@
|
|||||||
"type": "get_digit",
|
"type": "get_digit",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get_media_prefix",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "get_static_prefix",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "identifier",
|
||||||
"named": true
|
"named": true
|
||||||
@@ -2072,6 +2180,10 @@
|
|||||||
"type": "spaceless",
|
"type": "spaceless",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "static",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"named": true
|
"named": true
|
||||||
|
|||||||
+23399
-21221
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,181 @@
|
|||||||
|
==================
|
||||||
|
Static
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% static "a.css" %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(static
|
||||||
|
(filtered_value
|
||||||
|
(value
|
||||||
|
(literal
|
||||||
|
(string)))))
|
||||||
|
(content))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Static With A Variable Path
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% static path %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(static
|
||||||
|
(filtered_value
|
||||||
|
(value
|
||||||
|
(variable_attribute
|
||||||
|
(identifier)))))
|
||||||
|
(content))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Static With A Filtered Path
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% static "a.css"|upper %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(static
|
||||||
|
(filtered_value
|
||||||
|
(value
|
||||||
|
(literal
|
||||||
|
(string)))
|
||||||
|
(filter_expression
|
||||||
|
(filter))))
|
||||||
|
(content))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Static With As
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% static "a.css" as url %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(static
|
||||||
|
(filtered_value
|
||||||
|
(value
|
||||||
|
(literal
|
||||||
|
(string))))
|
||||||
|
variable: (identifier))
|
||||||
|
(content))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Static Without A Path
|
||||||
|
:error
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% static %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
Static With A Second Path
|
||||||
|
:error
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% static "a.css" "b.css" %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
Static With Anything After As
|
||||||
|
:error
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% static "a.css" as url junk %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
Get Static Prefix
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% get_static_prefix %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(get_static_prefix)
|
||||||
|
(content))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Get Static Prefix With As
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% get_static_prefix as prefix %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(get_static_prefix
|
||||||
|
variable: (identifier))
|
||||||
|
(content))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Get Media Prefix With As
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% get_media_prefix as prefix %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(get_media_prefix
|
||||||
|
variable: (identifier))
|
||||||
|
(content))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Get Static Prefix Without As
|
||||||
|
:error
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% get_static_prefix prefix %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
Get Static Prefix Without A Variable
|
||||||
|
:error
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% get_static_prefix as %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
Load Names The Library, Not The Tag
|
||||||
|
==================
|
||||||
|
|
||||||
|
{% load static %}{% static "a.css" %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(template
|
||||||
|
(content)
|
||||||
|
(load
|
||||||
|
(library
|
||||||
|
(identifier)))
|
||||||
|
(static
|
||||||
|
(filtered_value
|
||||||
|
(value
|
||||||
|
(literal
|
||||||
|
(string)))))
|
||||||
|
(content))
|
||||||
Reference in new issue
Block a user