Django/Jinja2 improvements (#1800)

This completely rewrites the Django language definition. It's now based on markup-templating.
This commit is contained in:
Michael Schmidt 2019-03-10 18:53:08 +01:00 committed by GitHub
parent af67c32e25
commit f2467488e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 652 additions and 111 deletions

File diff suppressed because one or more lines are too long

View File

@ -231,11 +231,7 @@
},
"django": {
"title": "Django/Jinja2",
"require": "markup",
"peerDependencies": [
"css",
"javascript"
],
"require": "markup-templating",
"alias": "jinja2",
"owner": "romanvm"
},

View File

@ -1,41 +1,60 @@
// Django/Jinja2 syntax definition for Prism.js <http://prismjs.com> syntax highlighter.
// Mostly it works OK but can paint code incorrectly on complex html/template tag combinations.
var _django_template = {
'property': {
pattern: /(?:{{|{%)[\s\S]*?(?:%}|}})/g,
greedy: true,
inside: {
'string': {
pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,
greedy: true
},
'keyword': /\b(?:\||load|verbatim|widthratio|ssi|firstof|for|url|ifchanged|csrf_token|lorem|ifnotequal|autoescape|now|templatetag|debug|cycle|ifequal|regroup|comment|filter|endfilter|if|spaceless|with|extends|block|include|else|empty|endif|endfor|as|endblock|endautoescape|endverbatim|trans|endtrans|[Tt]rue|[Ff]alse|[Nn]one|in|is|static|macro|endmacro|call|endcall|set|endset|raw|endraw)\b/,
'operator' : /[-+=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,
'function': /\b(?:_|abs|add|addslashes|attr|batch|callable|capfirst|capitalize|center|count|cut|d|date|default|default_if_none|defined|dictsort|dictsortreversed|divisibleby|e|equalto|escape|escaped|escapejs|even|filesizeformat|first|float|floatformat|force_escape|forceescape|format|get_digit|groupby|indent|int|iriencode|iterable|join|last|length|length_is|linebreaks|linebreaksbr|linenumbers|list|ljust|lower|make_list|map|mapping|number|odd|phone2numeric|pluralize|pprint|random|reject|rejectattr|removetags|replace|reverse|rjust|round|safe|safeseq|sameas|select|selectattr|sequence|slice|slugify|sort|string|stringformat|striptags|sum|time|timesince|timeuntil|title|trim|truncate|truncatechars|truncatechars_html|truncatewords|truncatewords_html|undefined|unordered_list|upper|urlencode|urlize|urlizetrunc|wordcount|wordwrap|xmlattr|yesno)\b/,
'important': /\b-?\d+(?:\.\d+)?\b/,
'variable': /\b\w+?\b/,
'punctuation' : /[[\];(),.:]/
}
}
};
(function (Prism) {
Prism.languages.django = Prism.languages.extend('markup', {'comment': /(?:<!--|{#)[\s\S]*?(?:#}|-->)/});
// Updated html tag pattern to allow template tags inside html tags
Prism.languages.django.tag.pattern = /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^>=]+))?)*\s*\/?>/i;
Prism.languages.insertBefore('django', 'entity', _django_template);
Prism.languages.insertBefore('inside', 'tag', _django_template, Prism.languages.django.tag);
Prism.languages.django = {
'comment': /^{#[\s\S]*?#}$/,
'tag': {
pattern: /(^{%[+-]?\s*)\w+/,
lookbehind: true,
alias: 'keyword'
},
'delimiter': {
pattern: /^{[{%][+-]?|[+-]?[}%]}$/,
alias: 'punctuation'
},
'string': {
pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,
greedy: true
},
'filter': {
pattern: /(\|)\w+/,
lookbehind: true,
alias: 'function'
},
'test': {
pattern: /(\bis\s+(?:not\s+)?)(?!not\b)\w+/,
lookbehind: true,
alias: 'function'
},
'function': /\b[a-z_]\w+(?=\s*\()/i,
'keyword': /\b(?:and|as|by|else|for|if|import|in|is|loop|not|or|recursive|with|without)\b/,
'operator': /[-+*/%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
'number': /\b\d+(?:\.\d+)?\b/,
'boolean': /[Tt]rue|[Ff]alse|[Nn]one/,
'variable': /\b\w+?\b/,
'punctuation': /[{}[\](),.:;]/
};
if (Prism.languages.javascript) {
// Combine js code and template tags painting inside <script> blocks
Prism.languages.insertBefore('inside', 'string', _django_template, Prism.languages.django.script);
Prism.languages.django.script.inside.string.inside = _django_template;
}
if (Prism.languages.css) {
// Combine css code and template tags painting inside <style> blocks
Prism.languages.insertBefore('inside', 'atrule', {'tag': _django_template.property}, Prism.languages.django.style);
Prism.languages.django.style.inside.string.inside = _django_template;
}
// Add an Jinja2 alias
Prism.languages.jinja2 = Prism.languages.django;
var pattern = /{{[\s\S]*?}}|{%[\s\S]*?%}|{#[\s\S]*?#}/g;
var markupTemplating = Prism.languages['markup-templating'];
Prism.hooks.add('before-tokenize', function (env) {
markupTemplating.buildPlaceholders(env, 'django', pattern);
});
Prism.hooks.add('after-tokenize', function (env) {
markupTemplating.tokenizePlaceholders(env, 'django');
});
// Add an Jinja2 alias
Prism.languages.jinja2 = Prism.languages.django;
Prism.hooks.add('before-tokenize', function (env) {
markupTemplating.buildPlaceholders(env, 'jinja2', pattern);
});
Prism.hooks.add('after-tokenize', function (env) {
markupTemplating.tokenizePlaceholders(env, 'jinja2');
});
})(Prism);

View File

@ -1 +1 @@
var _django_template={property:{pattern:/(?:{{|{%)[\s\S]*?(?:%}|}})/g,greedy:!0,inside:{string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/\b(?:\||load|verbatim|widthratio|ssi|firstof|for|url|ifchanged|csrf_token|lorem|ifnotequal|autoescape|now|templatetag|debug|cycle|ifequal|regroup|comment|filter|endfilter|if|spaceless|with|extends|block|include|else|empty|endif|endfor|as|endblock|endautoescape|endverbatim|trans|endtrans|[Tt]rue|[Ff]alse|[Nn]one|in|is|static|macro|endmacro|call|endcall|set|endset|raw|endraw)\b/,operator:/[-+=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,function:/\b(?:_|abs|add|addslashes|attr|batch|callable|capfirst|capitalize|center|count|cut|d|date|default|default_if_none|defined|dictsort|dictsortreversed|divisibleby|e|equalto|escape|escaped|escapejs|even|filesizeformat|first|float|floatformat|force_escape|forceescape|format|get_digit|groupby|indent|int|iriencode|iterable|join|last|length|length_is|linebreaks|linebreaksbr|linenumbers|list|ljust|lower|make_list|map|mapping|number|odd|phone2numeric|pluralize|pprint|random|reject|rejectattr|removetags|replace|reverse|rjust|round|safe|safeseq|sameas|select|selectattr|sequence|slice|slugify|sort|string|stringformat|striptags|sum|time|timesince|timeuntil|title|trim|truncate|truncatechars|truncatechars_html|truncatewords|truncatewords_html|undefined|unordered_list|upper|urlencode|urlize|urlizetrunc|wordcount|wordwrap|xmlattr|yesno)\b/,important:/\b-?\d+(?:\.\d+)?\b/,variable:/\b\w+?\b/,punctuation:/[[\];(),.:]/}}};Prism.languages.django=Prism.languages.extend("markup",{comment:/(?:<!--|{#)[\s\S]*?(?:#}|-->)/}),Prism.languages.django.tag.pattern=/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^>=]+))?)*\s*\/?>/i,Prism.languages.insertBefore("django","entity",_django_template),Prism.languages.insertBefore("inside","tag",_django_template,Prism.languages.django.tag),Prism.languages.javascript&&(Prism.languages.insertBefore("inside","string",_django_template,Prism.languages.django.script),Prism.languages.django.script.inside.string.inside=_django_template),Prism.languages.css&&(Prism.languages.insertBefore("inside","atrule",{tag:_django_template.property},Prism.languages.django.style),Prism.languages.django.style.inside.string.inside=_django_template),Prism.languages.jinja2=Prism.languages.django;
!function(e){e.languages.django={comment:/^{#[\s\S]*?#}$/,tag:{pattern:/(^{%[+-]?\s*)\w+/,lookbehind:!0,alias:"keyword"},delimiter:{pattern:/^{[{%][+-]?|[+-]?[}%]}$/,alias:"punctuation"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},filter:{pattern:/(\|)\w+/,lookbehind:!0,alias:"function"},test:{pattern:/(\bis\s+(?:not\s+)?)(?!not\b)\w+/,lookbehind:!0,alias:"function"},function:/\b[a-z_]\w+(?=\s*\()/i,keyword:/\b(?:and|as|by|else|for|if|import|in|is|loop|not|or|recursive|with|without)\b/,operator:/[-+*/%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,number:/\b\d+(?:\.\d+)?\b/,boolean:/[Tt]rue|[Ff]alse|[Nn]one/,variable:/\b\w+?\b/,punctuation:/[{}[\](),.:;]/};var n=/{{[\s\S]*?}}|{%[\s\S]*?%}|{#[\s\S]*?#}/g,o=e.languages["markup-templating"];e.hooks.add("before-tokenize",function(e){o.buildPlaceholders(e,"django",n)}),e.hooks.add("after-tokenize",function(e){o.tokenizePlaceholders(e,"django")}),e.languages.jinja2=e.languages.django,e.hooks.add("before-tokenize",function(e){o.buildPlaceholders(e,"jinja2",n)}),e.hooks.add("after-tokenize",function(e){o.tokenizePlaceholders(e,"jinja2")})}(Prism);

View File

@ -4,7 +4,7 @@
}
// The dependencies map is built automatically with gulp
var lang_dependencies = /*languages_placeholder[*/{"javascript":"clike","actionscript":"javascript","arduino":"cpp","aspnet":["markup","csharp"],"bison":"c","c":"clike","csharp":"clike","cpp":"c","coffeescript":"javascript","crystal":"ruby","css-extras":"css","d":"clike","dart":"clike","django":"markup","ejs":["javascript","markup-templating"],"erb":["ruby","markup-templating"],"fsharp":"clike","flow":"javascript","glsl":"clike","gml":"clike","go":"clike","groovy":"clike","haml":"ruby","handlebars":"markup-templating","haxe":"clike","java":"clike","javadoc":["markup","java","javadoclike"],"jolie":"clike","jsdoc":["javascript","javadoclike"],"js-extras":"javascript","jsonp":"json","json5":"json","kotlin":"clike","less":"css","markdown":"markup","markup-templating":"markup","n4js":"javascript","nginx":"clike","objectivec":"c","opencl":"cpp","parser":"markup","php":["clike","markup-templating"],"phpdoc":["php","javadoclike"],"php-extras":"php","plsql":"sql","processing":"clike","protobuf":"clike","pug":["markup","javascript"],"qore":"clike","jsx":["markup","javascript"],"tsx":["jsx","typescript"],"reason":"clike","ruby":"clike","sass":"css","scss":"css","scala":"java","smarty":"markup-templating","soy":"markup-templating","swift":"clike","tap":"yaml","textile":"markup","tt2":["clike","markup-templating"],"twig":"markup","typescript":"javascript","t4-cs":["t4-templating","csharp"],"t4-vb":["t4-templating","visual-basic"],"vala":"clike","vbnet":"basic","velocity":"markup","wiki":"markup","xeora":"markup","xquery":"markup"}/*]*/;
var lang_dependencies = /*languages_placeholder[*/{"javascript":"clike","actionscript":"javascript","arduino":"cpp","aspnet":["markup","csharp"],"bison":"c","c":"clike","csharp":"clike","cpp":"c","coffeescript":"javascript","crystal":"ruby","css-extras":"css","d":"clike","dart":"clike","django":"markup-templating","ejs":["javascript","markup-templating"],"erb":["ruby","markup-templating"],"fsharp":"clike","flow":"javascript","glsl":"clike","gml":"clike","go":"clike","groovy":"clike","haml":"ruby","handlebars":"markup-templating","haxe":"clike","java":"clike","javadoc":["markup","java","javadoclike"],"jolie":"clike","jsdoc":["javascript","javadoclike"],"js-extras":"javascript","jsonp":"json","json5":"json","kotlin":"clike","less":"css","markdown":"markup","markup-templating":"markup","n4js":"javascript","nginx":"clike","objectivec":"c","opencl":"cpp","parser":"markup","php":["clike","markup-templating"],"phpdoc":["php","javadoclike"],"php-extras":"php","plsql":"sql","processing":"clike","protobuf":"clike","pug":["markup","javascript"],"qore":"clike","jsx":["markup","javascript"],"tsx":["jsx","typescript"],"reason":"clike","ruby":"clike","sass":"css","scss":"css","scala":"java","smarty":"markup-templating","soy":"markup-templating","swift":"clike","tap":"yaml","textile":"markup","tt2":["clike","markup-templating"],"twig":"markup","typescript":"javascript","t4-cs":["t4-templating","csharp"],"t4-vb":["t4-templating","visual-basic"],"vala":"clike","vbnet":"basic","velocity":"markup","wiki":"markup","xeora":"markup","xquery":"markup"}/*]*/;
var lang_data = {};

View File

@ -1 +1 @@
!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.createElement){var c={javascript:"clike",actionscript:"javascript",arduino:"cpp",aspnet:["markup","csharp"],bison:"c",c:"clike",csharp:"clike",cpp:"c",coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",django:"markup",ejs:["javascript","markup-templating"],erb:["ruby","markup-templating"],fsharp:"clike",flow:"javascript",glsl:"clike",gml:"clike",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup-templating",haxe:"clike",java:"clike",javadoc:["markup","java","javadoclike"],jolie:"clike",jsdoc:["javascript","javadoclike"],"js-extras":"javascript",jsonp:"json",json5:"json",kotlin:"clike",less:"css",markdown:"markup","markup-templating":"markup",n4js:"javascript",nginx:"clike",objectivec:"c",opencl:"cpp",parser:"markup",php:["clike","markup-templating"],phpdoc:["php","javadoclike"],"php-extras":"php",plsql:"sql",processing:"clike",protobuf:"clike",pug:["markup","javascript"],qore:"clike",jsx:["markup","javascript"],tsx:["jsx","typescript"],reason:"clike",ruby:"clike",sass:"css",scss:"css",scala:"java",smarty:"markup-templating",soy:"markup-templating",swift:"clike",tap:"yaml",textile:"markup",tt2:["clike","markup-templating"],twig:"markup",typescript:"javascript","t4-cs":["t4-templating","csharp"],"t4-vb":["t4-templating","visual-basic"],vala:"clike",vbnet:"basic",velocity:"markup",wiki:"markup",xeora:"markup",xquery:"markup"},o={},a=document.getElementsByTagName("script"),e="components/";if((a=a[a.length-1]).hasAttribute("data-autoloader-path")){var t=a.getAttribute("data-autoloader-path").trim();0<t.length&&!/^[a-z]+:\/\//i.test(a.src)&&(e=t.replace(/\/?$/,"/"))}else/[\w-]+\.js$/.test(a.src)&&(e=a.src.replace(/[\w-]+\.js$/,"components/"));var u=Prism.plugins.autoloader={languages_path:e,use_minified:!0},s=function(a,e,c){"string"==typeof a&&(a=[a]);var t=0,s=a.length,r=function(){t<s?i(a[t],function(){t++,r()},function(){c&&c(a[t])}):t===s&&e&&e(a)};r()},i=function(l,n,p){var a=function(){var a=!1;0<=l.indexOf("!")&&(a=!0,l=l.replace("!",""));var e,c,t,s,r=o[l];if(r||(r=o[l]={}),n&&(r.success_callbacks||(r.success_callbacks=[]),r.success_callbacks.push(n)),p&&(r.error_callbacks||(r.error_callbacks=[]),r.error_callbacks.push(p)),!a&&Prism.languages[l])m(l);else if(!a&&r.error)k(l);else if(a||!r.loading){r.loading=!0;var i=u.languages_path+"prism-"+l+(u.use_minified?".min":"")+".js";e=i,c=function(){r.loading=!1,m(l)},t=function(){r.loading=!1,r.error=!0,k(l)},(s=document.createElement("script")).src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),c&&c()},s.onerror=function(){document.body.removeChild(s),t&&t()},document.body.appendChild(s)}},e=c[l];e&&e.length?s(e,a):a()},m=function(e){o[e]&&o[e].success_callbacks&&o[e].success_callbacks.length&&o[e].success_callbacks.forEach(function(a){a(e)})},k=function(e){o[e]&&o[e].error_callbacks&&o[e].error_callbacks.length&&o[e].error_callbacks.forEach(function(a){a(e)})};Prism.hooks.add("complete",function(a){a.element&&a.language&&!a.grammar&&"none"!==a.language&&function(a,e){var c=o[a];c||(c=o[a]={});var t=e.getAttribute("data-dependencies");!t&&e.parentNode&&"pre"===e.parentNode.tagName.toLowerCase()&&(t=e.parentNode.getAttribute("data-dependencies")),t=t?t.split(/\s*,\s*/g):[],s(t,function(){i(a,function(){Prism.highlightElement(e)})})}(a.language,a.element)})}}();
!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.createElement){var c={javascript:"clike",actionscript:"javascript",arduino:"cpp",aspnet:["markup","csharp"],bison:"c",c:"clike",csharp:"clike",cpp:"c",coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",django:"markup-templating",ejs:["javascript","markup-templating"],erb:["ruby","markup-templating"],fsharp:"clike",flow:"javascript",glsl:"clike",gml:"clike",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup-templating",haxe:"clike",java:"clike",javadoc:["markup","java","javadoclike"],jolie:"clike",jsdoc:["javascript","javadoclike"],"js-extras":"javascript",jsonp:"json",json5:"json",kotlin:"clike",less:"css",markdown:"markup","markup-templating":"markup",n4js:"javascript",nginx:"clike",objectivec:"c",opencl:"cpp",parser:"markup",php:["clike","markup-templating"],phpdoc:["php","javadoclike"],"php-extras":"php",plsql:"sql",processing:"clike",protobuf:"clike",pug:["markup","javascript"],qore:"clike",jsx:["markup","javascript"],tsx:["jsx","typescript"],reason:"clike",ruby:"clike",sass:"css",scss:"css",scala:"java",smarty:"markup-templating",soy:"markup-templating",swift:"clike",tap:"yaml",textile:"markup",tt2:["clike","markup-templating"],twig:"markup",typescript:"javascript","t4-cs":["t4-templating","csharp"],"t4-vb":["t4-templating","visual-basic"],vala:"clike",vbnet:"basic",velocity:"markup",wiki:"markup",xeora:"markup",xquery:"markup"},o={},a=document.getElementsByTagName("script"),e="components/";if((a=a[a.length-1]).hasAttribute("data-autoloader-path")){var t=a.getAttribute("data-autoloader-path").trim();0<t.length&&!/^[a-z]+:\/\//i.test(a.src)&&(e=t.replace(/\/?$/,"/"))}else/[\w-]+\.js$/.test(a.src)&&(e=a.src.replace(/[\w-]+\.js$/,"components/"));var u=Prism.plugins.autoloader={languages_path:e,use_minified:!0},s=function(a,e,c){"string"==typeof a&&(a=[a]);var t=0,s=a.length,r=function(){t<s?i(a[t],function(){t++,r()},function(){c&&c(a[t])}):t===s&&e&&e(a)};r()},i=function(l,n,p){var a=function(){var a=!1;0<=l.indexOf("!")&&(a=!0,l=l.replace("!",""));var e,c,t,s,r=o[l];if(r||(r=o[l]={}),n&&(r.success_callbacks||(r.success_callbacks=[]),r.success_callbacks.push(n)),p&&(r.error_callbacks||(r.error_callbacks=[]),r.error_callbacks.push(p)),!a&&Prism.languages[l])m(l);else if(!a&&r.error)k(l);else if(a||!r.loading){r.loading=!0;var i=u.languages_path+"prism-"+l+(u.use_minified?".min":"")+".js";e=i,c=function(){r.loading=!1,m(l)},t=function(){r.loading=!1,r.error=!0,k(l)},(s=document.createElement("script")).src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),c&&c()},s.onerror=function(){document.body.removeChild(s),t&&t()},document.body.appendChild(s)}},e=c[l];e&&e.length?s(e,a):a()},m=function(e){o[e]&&o[e].success_callbacks&&o[e].success_callbacks.length&&o[e].success_callbacks.forEach(function(a){a(e)})},k=function(e){o[e]&&o[e].error_callbacks&&o[e].error_callbacks.length&&o[e].error_callbacks.forEach(function(a){a(e)})};Prism.hooks.add("complete",function(a){a.element&&a.language&&!a.grammar&&"none"!==a.language&&function(a,e){var c=o[a];c||(c=o[a]={});var t=e.getAttribute("data-dependencies");!t&&e.parentNode&&"pre"===e.parentNode.tagName.toLowerCase()&&(t=e.parentNode.getAttribute("data-dependencies")),t=t?t.split(/\s*,\s*/g):[],s(t,function(){i(a,function(){Prism.highlightElement(e)})})}(a.language,a.element)})}}();

View File

@ -0,0 +1,56 @@
<style>
a {
{% if setColor %}
color: {{ bar }};
{% endif %}
}
</style>
----------------------------------------------------
[
["tag", [
["tag", [
["punctuation", "<"],
"style"
]],
["punctuation", ">"]
]],
["style", [
["language-css", [
["selector", "a"],
["punctuation", "{"],
["django", [
["delimiter", "{%"],
["tag", "if"],
["variable", "setColor"],
["delimiter", "%}"]
]],
["property", "color"],
["punctuation", ":"],
["django", [
["delimiter", "{{"],
["variable", "bar"],
["delimiter", "}}"]
]],
["punctuation", ";"],
["django", [
["delimiter", "{%"],
["tag", "endif"],
["delimiter", "%}"]
]],
["punctuation", "}"]
]]
]],
["tag", [
["tag", [
["punctuation", "</"],
"style"
]],
["punctuation", ">"]
]]
]
----------------------------------------------------
Checks for Django/Jinja2 code inside <style> elements.

View File

@ -0,0 +1,52 @@
<script>
{% if foo %}
var foo = {{ bar }};
{% endif %}
</script>
----------------------------------------------------
[
["tag", [
["tag", [
["punctuation", "<"],
"script"
]],
["punctuation", ">"]
]],
["script", [
["language-javascript", [
["django", [
["delimiter", "{%"],
["tag", "if"],
["variable", "foo"],
["delimiter", "%}"]
]],
["keyword", "var"],
" foo ",
["operator", "="],
["django", [
["delimiter", "{{"],
["variable", "bar"],
["delimiter", "}}"]
]],
["punctuation", ";"],
["django", [
["delimiter", "{%"],
["tag", "endif"],
["delimiter", "%}"]
]]
]]
]],
["tag", [
["tag", [
["punctuation", "</"],
"script"
]],
["punctuation", ">"]
]]
]
----------------------------------------------------
Checks for Django/Jinja2 code inside <script> elements.

View File

@ -0,0 +1,20 @@
{% true false none True False None %}
----------------------------------------------------
[
["django", [
["delimiter", "{%"],
["tag", "true"],
["boolean", "false"],
["boolean", "none"],
["boolean", "True"],
["boolean", "False"],
["boolean", "None"],
["delimiter", "%}"]
]]
]
----------------------------------------------------
Checks for booleans and none.

View File

@ -2,13 +2,23 @@
{# This a Django template example #}
{# Multi-line
comment #}
{# {{ }} {% %} #}
----------------------------------------------------
[
["comment", "{##}"],
["comment", "{# This a Django template example #}"],
["comment", "{# Multi-line\r\ncomment #}"]
["django", [
["comment", "{##}"]
]],
["django", [
["comment", "{# This a Django template example #}"]
]],
["django", [
["comment", "{# Multi-line\r\ncomment #}"]
]],
["django", [
["comment", "{# {{ }} {% %} #}"]
]]
]
----------------------------------------------------

View File

@ -0,0 +1,24 @@
{%%}
{%+ %}
{%- -%}
----------------------------------------------------
[
["django", [
["delimiter", "{%"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%+"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%-"],
["delimiter", "-%}"]
]]
]
----------------------------------------------------
Checks for delimiters.

View File

@ -0,0 +1,130 @@
{{ foo|cut|bar:5 }}
{{ foo|bar('baz') }}
{{ my_date|date:"Y-m-d" }}
{{ value|truncatechars:9 }}
{{ name|striptags|title }}
{{ listx|join(', ') }}
{{ "%s - %s"|format("Hello?", "Foo!") }}
{{ users|join(', ', attribute='username') }}
{{ mytext|urlize(40, true) }}
{{ [1, 2, -3]|max }}
----------------------------------------------------
[
["django", [
["delimiter", "{{"],
["variable", "foo"],
["operator", "|"],
["filter", "cut"],
["operator", "|"],
["filter", "bar"],
["punctuation", ":"],
["number", "5"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["variable", "foo"],
["operator", "|"],
["filter", "bar"],
["punctuation", "("],
["string", "'baz'"],
["punctuation", ")"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["variable", "my_date"],
["operator", "|"],
["filter", "date"],
["punctuation", ":"],
["string", "\"Y-m-d\""],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["variable", "value"],
["operator", "|"],
["filter", "truncatechars"],
["punctuation", ":"],
["number", "9"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["variable", "name"],
["operator", "|"],
["filter", "striptags"],
["operator", "|"],
["filter", "title"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["variable", "listx"],
["operator", "|"],
["filter", "join"],
["punctuation", "("],
["string", "', '"],
["punctuation", ")"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["string", "\"%s - %s\""],
["operator", "|"],
["filter", "format"],
["punctuation", "("],
["string", "\"Hello?\""],
["punctuation", ","],
["string", "\"Foo!\""],
["punctuation", ")"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["variable", "users"],
["operator", "|"],
["filter", "join"],
["punctuation", "("],
["string", "', '"],
["punctuation", ","],
["variable", "attribute"],
["operator", "="],
["string", "'username'"],
["punctuation", ")"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["variable", "mytext"],
["operator", "|"],
["filter", "urlize"],
["punctuation", "("],
["number", "40"],
["punctuation", ","],
["boolean", "true"],
["punctuation", ")"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{{"],
["punctuation", "["],
["number", "1"],
["punctuation", ","],
["number", "2"],
["punctuation", ","],
["operator", "-"],
["number", "3"],
["punctuation", "]"],
["operator", "|"],
["filter", "max"],
["delimiter", "}}"]
]]
]
----------------------------------------------------
Checks for filters.

View File

@ -0,0 +1,96 @@
{% for value in values recursive %}
{% if loop.previtem is defined and value > loop.previtem %}
The value just increased!
{% endif %}
{{ value }}
{% if loop.nextitem is defined and loop.nextitem > value %}
The value will increase even more!
{% endif %}
{% endfor %}
{% for user in users if not user.hidden %}
----------------------------------------------------
[
["django", [
["delimiter", "{%"],
["tag", "for"],
["variable", "value"],
["keyword", "in"],
["variable", "values"],
["keyword", "recursive"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%"],
["tag", "if"],
["keyword", "loop"],
["punctuation", "."],
["variable", "previtem"],
["keyword", "is"],
["test", "defined"],
["keyword", "and"],
["variable", "value"],
["operator", ">"],
["keyword", "loop"],
["punctuation", "."],
["variable", "previtem"],
["delimiter", "%}"]
]],
"\r\n The value just increased!\r\n ",
["django", [
["delimiter", "{%"],
["tag", "endif"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{{"],
["variable", "value"],
["delimiter", "}}"]
]],
["django", [
["delimiter", "{%"],
["tag", "if"],
["keyword", "loop"],
["punctuation", "."],
["variable", "nextitem"],
["keyword", "is"],
["test", "defined"],
["keyword", "and"],
["keyword", "loop"],
["punctuation", "."],
["variable", "nextitem"],
["operator", ">"],
["variable", "value"],
["delimiter", "%}"]
]],
"\r\n The value will increase even more!\r\n ",
["django", [
["delimiter", "{%"],
["tag", "endif"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%"],
["tag", "endfor"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%"],
["tag", "for"],
["variable", "user"],
["keyword", "in"],
["variable", "users"],
["keyword", "if"],
["keyword", "not"],
["variable", "user"],
["punctuation", "."],
["variable", "hidden"],
["delimiter", "%}"]
]]
]
----------------------------------------------------
Checks for for-loop related features.

View File

@ -0,0 +1,73 @@
<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">
<a href="{{ url('admin:index') }}">Administration</a>
----------------------------------------------------
[
["tag", [
["tag", [
["punctuation", "<"],
"img"
]],
["attr-name", [
"src"
]],
["attr-value", [
["punctuation", "="],
["punctuation", "\""],
["django", [
["delimiter", "{{"],
["function", "static"],
["punctuation", "("],
["string", "'path/to/company-logo.png'"],
["punctuation", ")"],
["delimiter", "}}"]
]],
["punctuation", "\""]
]],
["attr-name", [
"alt"
]],
["attr-value", [
["punctuation", "="],
["punctuation", "\""],
"Company Logo",
["punctuation", "\""]
]],
["punctuation", ">"]
]],
["tag", [
["tag", [
["punctuation", "<"], "a"
]],
["attr-name", [
"href"
]],
["attr-value", [
["punctuation", "="],
["punctuation", "\""],
["django", [
["delimiter", "{{"],
["function", "url"],
["punctuation", "("],
["string", "'admin:index'"],
["punctuation", ")"],
["delimiter", "}}"]
]],
["punctuation", "\""]
]],
["punctuation", ">"]
]],
"Administration",
["tag", [
["tag", [
["punctuation", "</"],
"a"
]],
["punctuation", ">"]
]]
]
----------------------------------------------------
Checks for functions.

View File

@ -0,0 +1,50 @@
{% some_tag
and
as
by
else
for
if
import
in
is
loop
not
or
recursive
with
without
%}
----------------------------------------------------
[
["django", [
["delimiter", "{%"],
["tag", "some_tag"],
["keyword", "and"],
["keyword", "as"],
["keyword", "by"],
["keyword", "else"],
["keyword", "for"],
["keyword", "if"],
["keyword", "import"],
["keyword", "in"],
["keyword", "is"],
["test", "loop"],
["keyword", "not"],
["keyword", "or"],
["keyword", "recursive"],
["keyword", "with"],
["keyword", "without"],
["delimiter", "%}"]
]]
]
----------------------------------------------------
Checks for keywords.

View File

@ -1,64 +0,0 @@
{% extends "base_generic.html" %}
{% block body %}
<a href="{{ story.get_absolute_url }}">
{{ story.headline|upper }}
</a>
{% endblock %}
----------------------------------------------------
[
["property", [
"{% ",
["keyword", "extends"],
["string", "\"base_generic.html\""],
" %}"
]],
["property", [
"{% ",
["keyword", "block"],
["variable", "body"],
" %}"
]],
["tag", [
["tag", [
["punctuation", "<"],
"a"
]],
["attr-name", ["href=\""]],
["property", [
"{{ ",
["variable", "story"],
["punctuation", "."],
["variable", "get_absolute_url"],
" }}"
]],
["attr-name", ["\""]],
["punctuation", ">"]
]],
["property", [
"{{ ",
["variable", "story"],
["punctuation", "."],
["variable", "headline"],
["keyword", "|"],
["function", "upper"],
" }}"
]],
["tag", [
["tag", [
["punctuation", "</"],
"a"
]],
["punctuation", ">"]
]],
["property", [
"{% ",
["keyword", "endblock"],
" %}"
]]
]
----------------------------------------------------
Checks for properties.

View File

@ -0,0 +1,36 @@
{% block %}
{% endif %}
{% foo %}
{% foo_bar some.variable %}
----------------------------------------------------
[
["django", [
["delimiter", "{%"],
["tag", "block"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%"],
["tag", "endif"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%"],
["tag", "foo"],
["delimiter", "%}"]
]],
["django", [
["delimiter", "{%"],
["tag", "foo_bar"],
["variable", "some"],
["punctuation", "."],
["variable", "variable"],
["delimiter", "%}"]
]]
]
----------------------------------------------------
Checks for tags.

View File

@ -0,0 +1,23 @@
{% if foo is defined and bar is not baz %}
----------------------------------------------------
[
["django", [
["delimiter", "{%"],
["tag", "if"],
["variable", "foo"],
["keyword", "is"],
["test", "defined"],
["keyword", "and"],
["variable", "bar"],
["keyword", "is"],
["keyword", "not"],
["test", "baz"],
["delimiter", "%}"]
]]
]
----------------------------------------------------
Checks for tests.

View File

@ -0,0 +1,20 @@
{{ foo.bar['baz'] }}
----------------------------------------------------
[
["django", [
["delimiter", "{{"],
["variable", "foo"],
["punctuation", "."],
["variable", "bar"],
["punctuation", "["],
["string", "'baz'"],
["punctuation", "]"],
["delimiter", "}}"]
]]
]
----------------------------------------------------
Checks for variables.