├── README.md ├── django-templates.coffee ├── grammars └── html (django).cson ├── package.json ├── settings └── django-templates.cson └── snippets └── django-templates.cson /README.md: -------------------------------------------------------------------------------- 1 | # Atom support for Django Templates 2 | 3 | Atom support for Django HTML templates. Originally forked from [python-django-templates.tmbundle](https://github.com/textmate/python-django-templates.tmbundle) and [Djaneiro](https://github.com/squ1b3r/Djaneiro). 4 | 5 | ## Default Grammar 6 | It's common for Django templates to have a `.html` extension. Unfortunately, this doesn't give Atom a ton of help in determining whether it should use the Django Templates grammar or the normal HTML grammar. If you put part of the path to your Django project in the "Default to Django Templates For File Paths Containing" setting, we'll change the grammar to Django Templates for any files that are `.html` and whose file paths contain the string you enter. 7 | 8 | ![Settings Example](https://f.cloud.github.com/assets/69549/2429497/3fd16d50-ac86-11e3-9b78-7c2bc051212c.png) 9 | 10 | ## Emmet Integration 11 | Out of the box, Emmet isn't aware of the Django HTML Templates grammar, so Django HTML Templates uses Atom's tab-based HTML autocompletion rather than Emmet's. As the [Emmet-Atom Readme](https://github.com/emmetio/emmet-atom) explains, this is an easy fix. All you have to do is add Django Templates to the the list of grammars in Emmet's `keymaps/emmet.cson` file: 12 | 13 | ``` cson 14 | # language-specific Tab triggers 15 | # you can add more triggers by changing `grammar` attribute valuse 16 | '[...], atom-text-editor[data-grammar="text html django"]:not([mini])': 17 | ``` 18 | 19 | ## Release Notes 20 | 21 | * 0.5.0: Fix scoped-properties deprecation (thanks djch!). Add elif and with keywords (thanks batisteo!) 22 | * 0.4.0: Allow multiple path fragments (thanks MetaMemoryT!). Fix deprecation errors (thanks djch!) 23 | * 0.3.0: Added an optional setting to activate the Django Template grammar based on file path. 24 | * 0.2.0: Fixed a bug causing the removal of comments to slice away closing `>`. 25 | * 0.1.0: Initial release. 26 | -------------------------------------------------------------------------------- /django-templates.coffee: -------------------------------------------------------------------------------- 1 | class DjangoTemplates 2 | desc: "defaultToDjangoTemplatesForFilePathsContaining" 3 | 4 | configKey: "django-templates.#{ DjangoTemplates.prototype.desc }" 5 | 6 | config: 7 | defaultToDjangoTemplatesForFilePathsContaining: 8 | type: 'array' 9 | default: [] 10 | items: 11 | type: 'string' 12 | 13 | activate: (state) -> 14 | @watchEditors() 15 | 16 | watchEditors: -> 17 | atom.workspace.observeTextEditors (editor) => 18 | path = editor.getPath() 19 | if path 20 | if path.indexOf('.html') isnt -1 21 | matches = false 22 | for frag in atom.config.get @configKey 23 | if path.indexOf(frag) 24 | matches = true 25 | break 26 | if matches 27 | grammar = atom.grammars.grammarForScopeName('text.html.django') 28 | editor.setGrammar(grammar) 29 | 30 | module.exports = new DjangoTemplates 31 | -------------------------------------------------------------------------------- /grammars/html (django).cson: -------------------------------------------------------------------------------- 1 | 'fileTypes': [ 2 | 'html' 3 | 'html.django' 4 | ] 5 | 'name': 'HTML (Django)' 6 | 'patterns': [ 7 | { 8 | 'comment': 'Since html is valid in Django templates include the html patterns' 9 | 'include': 'text.html.basic' 10 | } 11 | { 12 | 'begin': '{% comment %}' 13 | 'end': '{% endcomment %}' 14 | 'name': 'comment.block.django.template' 15 | } 16 | { 17 | 'begin': '{#' 18 | 'end': '#}' 19 | 'name': 'comment.line.django.template' 20 | } 21 | { 22 | 'begin': '{{' 23 | 'end': '}}' 24 | 'name': 'variable.other.django.template' 25 | } 26 | { 27 | 'begin': '({%)' 28 | 'captures': 29 | '1': 30 | 'name': 'entity.other.django.tagbraces' 31 | 'end': '(%})' 32 | 'name': 'meta.scope.django.template.tag' 33 | 'patterns': [ 34 | { 35 | 'match': '\\b(autoescape|endautoescape|block|endblock|trans|blocktrans|endblocktrans|plural|debug|extends|filter|firstof|for|endfor|if|include|else|elif|endif|ifchanged|endifchanged|ifequal|endifequal|ifnotequal|endifnotequal|load|now|regroup|ssi|spaceless|templatetag|widthratio|with|endwith)\\b' 36 | 'name': 'keyword.control.django.template' 37 | } 38 | { 39 | 'match': '\\b(and|or|not|in|by|as)\\b' 40 | 'name': 'keyword.operator.django.template' 41 | } 42 | { 43 | 'match': '\\|(add|addslashes|capfirst|center|cut|date|default|default_if_none|dictsort|dictsortreversed|divisibleby|escape|filesizeformat|first|fix_ampersands|floatformat|get_digit|join|length|length_is|linebreaks|linebreaksbr|linenumbers|ljust|lower|make_list|phone2numeric|pluralize|pprint|random|removetags|rjust|safe|slice|slugify|stringformat|striptags|time|timesince|title|truncatewords|unordered_list|upper|urlencode|urlize|urlizetrunc|wordcount|wordwrap|yesno)\\b' 44 | 'name': 'support.function.filter.django' 45 | } 46 | { 47 | 'begin': '(\'|")' 48 | 'end': '\\1' 49 | 'name': 'string.other.django.template.tag' 50 | } 51 | { 52 | 'match': '[a-zA-Z_]+' 53 | 'name': 'string.unquoted.django.template.tag' 54 | } 55 | ] 56 | } 57 | ] 58 | 'scopeName': 'text.html.django' 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "django-templates", 3 | "version": "0.5.0", 4 | "description": "Atom support for Django templates.", 5 | "license": "MIT", 6 | "main": "django-templates.coffee", 7 | "engines": { 8 | "atom": ">0.50.0" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/benjohnson/atom-django-templates" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/benjohnson/atom-django-templates/issues" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /settings/django-templates.cson: -------------------------------------------------------------------------------- 1 | '.text.html.django': 2 | 'editor': 3 | 'commentStart': '{# ' 4 | 'commentEnd': '#}' 5 | -------------------------------------------------------------------------------- /snippets/django-templates.cson: -------------------------------------------------------------------------------- 1 | '.text.html.django': 2 | 'autoescape': 3 | 'prefix': 'autoescape' 4 | 'body': '{% autoescape ${1:off} %}\n\t$2\n{% endautoescape %}' 5 | 'block': 6 | 'prefix': 'block' 7 | 'body': '{% block ${1} %}\n\t$2\n{% endblock %}' 8 | 'blocktrans': 9 | 'prefix': 'blocktrans' 10 | 'body': '{% blocktrans ${1:with ${2:var1} as ${3:var2}} %}\n\t$4\n{% endblocktrans %}' 11 | 'comment': 12 | 'prefix': 'comment' 13 | 'body': '{% comment %}\n\t$1\n{% endcomment %}' 14 | 'var': 15 | 'prefix': 'var' 16 | 'body': '{{ $1 }}' 17 | 'csrf': 18 | 'prefix': 'csrf', 19 | 'body': '{% csrf_token %}' 20 | 'cycle': 21 | 'prefix': 'cycle' 22 | 'body': '{% cycle $1 as $2 %}' 23 | 'debug': 24 | 'prefix': 'debug' 25 | 'body': '{% debug %}' 26 | 'elif': 27 | 'prefix': 'else' 28 | 'body': '{% elif $1 %}' 29 | 'else': 30 | 'prefix': 'else' 31 | 'body': '{% else %}' 32 | 'empty': 33 | 'prefix': 'empty' 34 | 'body': '{% empty %}' 35 | 'extends': 36 | 'prefix': 'extends' 37 | 'body': '{% extends "$1" %}' 38 | 'filter': 39 | 'prefix': 'filter' 40 | 'body': '{% filter $1 %}\n\t$2\n{% endfilter %}' 41 | 'firstof': 42 | 'prefix': 'firstof' 43 | 'body': '{% firstof $1 %}' 44 | 'for': 45 | 'prefix': 'for' 46 | 'body': '{% for $1 in $2 %}\n\t$3\n{% endfor %}' 47 | 'if': 48 | 'prefix': 'if' 49 | 'body': '{% if $1 %}$0{% endif %}' 50 | 'ife': 51 | 'prefix': 'ife' 52 | 'body': '{% if $1 %}$2{% else %}$3{% endif %}' 53 | 'ifchanged': 54 | 'prefix': 'ifchanged' 55 | 'body': '{% ifchanged %}$0{% endifchanged %}' 56 | 'ifequal': 57 | 'prefix': 'ifequal' 58 | 'body': '{% ifequal $1 $2 %}$0{% endifequal %}' 59 | 'ifnotequal': 60 | 'prefix': 'ifnotequal' 61 | 'body': '{% ifnotequal $1 $2 %}$0{% endifnotequal %}' 62 | 'include': 63 | 'prefix': 'include' 64 | 'body': '{% include "$1" %}' 65 | 'load': 66 | 'prefix': 'load' 67 | 'body': '{% load $1 %}' 68 | 'now': 69 | 'prefix': 'now' 70 | 'body': '{% now "$1" %}' 71 | 'media': 72 | 'prefix': 'media' 73 | 'body': '{{ MEDIA_URL }}' 74 | 'regroup': 75 | 'prefix': 'regroup' 76 | 'body': '{% regroup $1 by $2 as $3 %}' 77 | 'spaceless': 78 | 'prefix': 'spaceless' 79 | 'body': '{% spaceless %}$0{% endspaceless %}' 80 | 'ssi': 81 | 'prefix': 'ssi' 82 | 'body': '{% ssi $1 ${2:parsed} %}' 83 | 'super': 84 | 'prefix': 'super' 85 | 'body': '{{ block.super }}' 86 | 'static': 87 | 'prefix': 'static' 88 | 'body': '{% static "$1" %}' 89 | 'tag': 90 | 'prefix': 'tag' 91 | 'body': '{% $1 %}' 92 | 'templatetag': 93 | 'prefix': 'templatetag' 94 | 'body': '{% templatetag $1 %}' 95 | 'trans': 96 | 'prefix': 'trans' 97 | 'body': '{% trans "${1:string to translate}" %}' 98 | 'url': 99 | 'prefix': 'url' 100 | 'body': '{% url \'$1\' %}' 101 | 'widthratio': 102 | 'prefix': 'widthratio' 103 | 'body': '{% widthratio ${1:this_value} ${2:max_value} ${3:100} %}' 104 | 'with': 105 | 'prefix': 'with' 106 | 'body': '{% with ${1:var} as ${2:name} %}{{ ${3:$2} }}{% endwith %}' 107 | --------------------------------------------------------------------------------