├── icon.png ├── example.png ├── jinja.configuration.json ├── example.j2 ├── .vscode └── launch.json ├── syntaxes ├── jinja-yaml.json ├── jinja-html.json └── jinja.json ├── LICENSE ├── package.json └── README.md /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholroyd/vscode-jinja/HEAD/icon.png -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholroyd/vscode-jinja/HEAD/example.png -------------------------------------------------------------------------------- /jinja.configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "#" 4 | }, 5 | "brackets": [ 6 | ["{", "}"], 7 | ["[", "]"], 8 | ["(", ")"], 9 | ["{%", "%}"] 10 | ] 11 | } -------------------------------------------------------------------------------- /example.j2: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 | 8 | {% endblock %} 9 | 10 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.1", 3 | "configurations": [ 4 | { 5 | "name": "Launch Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "runtimeExecutable": "${execPath}", 9 | "args": [ 10 | "--extensionDevelopmentPath=${workspaceRoot}" 11 | ], 12 | "stopOnEntry": false, 13 | "sourceMaps": true 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /syntaxes/jinja-yaml.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jinja-yaml", 3 | "scopeName": "text.yaml.jinja", 4 | "comment": "Jinja Template Engine in YAML", 5 | "fileTypes": [ 6 | "j2", 7 | "yml", 8 | "yaml" 9 | ], 10 | "firstLineMatch": "^{% extends [\"'][^\"']+[\"'] %}", 11 | "patterns": [ 12 | { 13 | "include": "source.jinja" 14 | }, 15 | { 16 | "include": "source.yaml" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /syntaxes/jinja-html.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jinja-html", 3 | "scopeName": "text.html.jinja", 4 | "comment": "Jinja Template Engine in HTML", 5 | "fileTypes": [ 6 | "j2", 7 | "html" 8 | ], 9 | "firstLineMatch": "^{% extends [\"'][^\"']+[\"'] %}", 10 | "foldingStartMarker": "(<(?i:(head|table|tr|div|style|script|ul|ol|form|dl))\\b.*?>|{%\\s*(block|filter|for|if|macro|raw))", 11 | "foldingStopMarker": "(<\/(?i:(head|table|tr|div|style|script|ul|ol|form|dl))\\b.*?>|{%\\s*(endblock|endfilter|endfor|endif|endmacro|endraw)\\s*%})", 12 | "patterns": [ 13 | { 14 | "include": "source.jinja" 15 | }, 16 | { 17 | "include": "text.html.basic" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 William Holroyd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jinja", 3 | "version": "0.0.8", 4 | "publisher": "wholroyd", 5 | "author": { 6 | "name": "William Holroyd" 7 | }, 8 | "license": "MIT", 9 | "icon": "icon.png", 10 | "description": "Jinja template language support for Visual Studio Code", 11 | "displayName": "Jinja", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/wholroyd/vscode-jinja.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/wholroyd/vscode-jinja/issues" 18 | }, 19 | "categories": [ 20 | "Languages", 21 | "Snippets", 22 | "Linters" 23 | ], 24 | "engines": { 25 | "vscode": "^1.0.0" 26 | }, 27 | "contributes": { 28 | "languages": [ 29 | { 30 | "id": "jinja", 31 | "aliases": [ 32 | "Jinja" 33 | ], 34 | "extensions": [".j2"], 35 | "configuration": "./jinja.configuration.json" 36 | } 37 | ], 38 | "grammars": [ 39 | { 40 | "language": "jinja", 41 | "scopeName": "source.jinja", 42 | "path": "./syntaxes/jinja.json" 43 | }, 44 | { 45 | "language": "html", 46 | "scopeName": "text.html.jinja", 47 | "path": "./syntaxes/jinja-html.json" 48 | }, 49 | { 50 | "language": "yaml", 51 | "scopeName": "text.yaml.jinja", 52 | "path": "./syntaxes/jinja-yaml.json" 53 | } 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jinja for Visual Studio Code 2 | 3 | [![Join the chat at https://gitter.im/wholroyd/vscode-jinja](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/wholroyd/vscode-jinja?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | This extension adds language colorization support for the Jinja template language to VS Code. 6 | 7 | ![IDE](https://raw.githubusercontent.com/wholroyd/vscode-jinja/master/example.png) 8 | 9 | ## Using 10 | 11 | First, you will need to install Visual Studio Code `1.0.0` or higher. In the command palette (`cmd-shift-p`) select `Install Extension` and choose `Jinja`. 12 | 13 | The downside of the Jinja language is that there is no defined file extension and as such, there is no way to detect it automatically in all cases. If you'd like to associate a file extension with this language, use the `file.association` setting as described [here](https://code.visualstudio.com/docs/languages/overview#_adding-a-file-extension-to-a-language). 14 | 15 | ### ...as of v0.0.8 16 | 17 | A change was made to Visual Studio Code a while back which changed how languages are injected and used together. Such as using Jinja with HTML, YAML, JSON, or any other language you want to templatize. As a result, the extension will only highlight for the actual Jinja language or the other language, but not both. It's an unfortunate short term solution to give YAML and HTML options back to users until the extension can be revamped to support Jinja with any other language. 18 | 19 | ## Contributing 20 | 21 | If you are interested in making this extension better, I will gladly take pull requests that expand it to add intellisense, hovers and validators. If you're not familiar with working on Visual Studio Code extensions, check out the VS Code extenders documentation at 22 | https://code.visualstudio.com/docs. 23 | 24 | To get started on the extension... 25 | 26 | 1. Go to the Debug viewlet and select `Launch Extension` then hit run (`F5`). This will launch a second instance of Code with the extension from the first window loaded. 27 | 28 | 2. As you make changes, you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the second Code window to load any changes. 29 | 30 | If you have a previous release of the extension installed and you perform these steps, Code will temporarily override the locally installed version instead for the one you're working on for the second window. The first (main) window will remain to have the locally installed, prior version installed and enabled until an update is available. 31 | 32 | ## License 33 | [MIT](LICENSE) 34 | -------------------------------------------------------------------------------- /syntaxes/jinja.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jinja", 3 | "scopeName": "source.jinja", 4 | "comment": "Jinja Template Engine", 5 | "fileTypes": ["j2"], 6 | "foldingStartMarker": "({%\\s*(block|filter|for|if|macro|raw))", 7 | "foldingStopMarker": "({%\\s*(endblock|endfilter|endfor|endif|endmacro|endraw)\\s*%})", 8 | "patterns": [ 9 | { 10 | "begin": "({%)\\s*(raw)\\s*(%})", 11 | "captures": { 12 | "1": { 13 | "name": "entity.other.jinja.delimiter.tag" 14 | }, 15 | "2": { 16 | "name": "keyword.control.jinja" 17 | }, 18 | "3": { 19 | "name": "entity.other.jinja.delimiter.tag" 20 | } 21 | }, 22 | "end": "({%)\\s*(endraw)\\s*(%})", 23 | "name": "comment.block.jinja.raw" 24 | }, 25 | { 26 | "begin": "{#-?", 27 | "captures": [ 28 | { 29 | "name": "entity.other.jinja.delimiter.comment" 30 | } 31 | ], 32 | "end": "-?#}", 33 | "name": "comment.block.jinja" 34 | }, 35 | { 36 | "begin": "{{-?", 37 | "captures": [ 38 | { 39 | "name": "entity.other.jinja.delimiter.variable" 40 | } 41 | ], 42 | "end": "-?}}", 43 | "name": "meta.scope.jinja.variable", 44 | "patterns": [ 45 | { 46 | "include": "#expression" 47 | } 48 | ] 49 | }, 50 | { 51 | "begin": "{%-?", 52 | "captures": [ 53 | { 54 | "name": "entity.other.jinja.delimiter.tag" 55 | } 56 | ], 57 | "end": "-?%}", 58 | "name": "meta.scope.jinja.tag", 59 | "patterns": [ 60 | { 61 | "include": "#expression" 62 | } 63 | ] 64 | } 65 | ], 66 | "repository": { 67 | "escaped_char": { 68 | "match": "\\\\x[0-9A-F]{2}", 69 | "name": "constant.character.escape.hex.jinja" 70 | }, 71 | "escaped_unicode_char": { 72 | "captures": { 73 | "1": { 74 | "name": "constant.character.escape.unicode.16-bit-hex.jinja" 75 | }, 76 | "2": { 77 | "name": "constant.character.escape.unicode.32-bit-hex.jinja" 78 | }, 79 | "3": { 80 | "name": "constant.character.escape.unicode.name.jinja" 81 | } 82 | }, 83 | "match": "(\\\\U[0-9A-Fa-f]{8})|(\\\\u[0-9A-Fa-f]{4})|(\\\\N\\{[a-zA-Z ]+\\})" 84 | }, 85 | "expression": { 86 | "patterns": [ 87 | { 88 | "captures": { 89 | "1": { 90 | "name": "keyword.control.jinja" 91 | }, 92 | "2": { 93 | "name": "variable.other.jinja.block" 94 | } 95 | }, 96 | "match": "\\s*\\b(block)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b" 97 | }, 98 | { 99 | "captures": { 100 | "1": { 101 | "name": "keyword.control.jinja" 102 | }, 103 | "2": { 104 | "name": "variable.other.jinja.filter" 105 | } 106 | }, 107 | "match": "\\s*\\b(filter)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b" 108 | }, 109 | { 110 | "captures": { 111 | "1": { 112 | "name": "keyword.control.jinja" 113 | }, 114 | "2": { 115 | "name": "variable.other.jinja.test" 116 | } 117 | }, 118 | "match": "\\s*\\b(is)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b" 119 | }, 120 | { 121 | "captures": { 122 | "1": { 123 | "name": "keyword.control.jinja" 124 | } 125 | }, 126 | "match": "(?<=\\{\\%-|\\{\\%)\\s*\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b(?!\\s*[,=])" 127 | }, 128 | { 129 | "match": "\\b(and|else|if|in|import|not|or|recursive|with(out)?\\s+context)\\b", 130 | "name": "keyword.control.jinja" 131 | }, 132 | { 133 | "match": "\\b(true|false|none)\\b", 134 | "name": "constant.language.jinja" 135 | }, 136 | { 137 | "match": "\\b(loop|super|self|varargs|kwargs)\\b", 138 | "name": "variable.language.jinja" 139 | }, 140 | { 141 | "match": "[a-zA-Z_][a-zA-Z0-9_]*", 142 | "name": "variable.other.jinja" 143 | }, 144 | { 145 | "match": "(\\+|\\-|\\*\\*|\\*|\/\/|\/|%)", 146 | "name": "keyword.operator.arithmetic.jinja" 147 | }, 148 | { 149 | "captures": { 150 | "1": { 151 | "name": "punctuation.other.jinja" 152 | }, 153 | "2": { 154 | "name": "variable.other.jinja.filter" 155 | } 156 | }, 157 | "match": "(\\|)([a-zA-Z_][a-zA-Z0-9_]*)" 158 | }, 159 | { 160 | "captures": { 161 | "1": { 162 | "name": "punctuation.other.jinja" 163 | }, 164 | "2": { 165 | "name": "variable.other.jinja.attribute" 166 | } 167 | }, 168 | "match": "(\\.)([a-zA-Z_][a-zA-Z0-9_]*)" 169 | }, 170 | { 171 | "begin": "\\[", 172 | "captures": [ 173 | { 174 | "name": "punctuation.other.jinja" 175 | } 176 | ], 177 | "end": "\\]", 178 | "patterns": [ 179 | { 180 | "include": "#expression" 181 | } 182 | ] 183 | }, 184 | { 185 | "begin": "\\(", 186 | "captures": [ 187 | { 188 | "name": "punctuation.other.jinja" 189 | } 190 | ], 191 | "end": "\\)", 192 | "patterns": [ 193 | { 194 | "include": "#expression" 195 | } 196 | ] 197 | }, 198 | { 199 | "begin": "\\{", 200 | "captures": [ 201 | { 202 | "name": "punctuation.other.jinja" 203 | } 204 | ], 205 | "end": "\\}", 206 | "patterns": [ 207 | { 208 | "include": "#expression" 209 | } 210 | ] 211 | }, 212 | { 213 | "match": "(\\.|:|\\||,)", 214 | "name": "punctuation.other.jinja" 215 | }, 216 | { 217 | "match": "(==|<=|=>|<|>|!=)", 218 | "name": "keyword.operator.comparison.jinja" 219 | }, 220 | { 221 | "match": "=", 222 | "name": "keyword.operator.assignment.jinja" 223 | }, 224 | { 225 | "begin": "\"", 226 | "beginCaptures": [ 227 | { 228 | "name": "punctuation.definition.string.begin.jinja" 229 | } 230 | ], 231 | "end": "\"", 232 | "endCaptures": [ 233 | { 234 | "name": "punctuation.definition.string.end.jinja" 235 | } 236 | ], 237 | "name": "string.quoted.double.jinja", 238 | "patterns": [ 239 | { 240 | "include": "#string" 241 | } 242 | ] 243 | }, 244 | { 245 | "begin": "'", 246 | "beginCaptures": [ 247 | { 248 | "name": "punctuation.definition.string.begin.jinja" 249 | } 250 | ], 251 | "end": "'", 252 | "endCaptures": [ 253 | { 254 | "name": "punctuation.definition.string.end.jinja" 255 | } 256 | ], 257 | "name": "string.quoted.single.jinja", 258 | "patterns": [ 259 | { 260 | "include": "#string" 261 | } 262 | ] 263 | }, 264 | { 265 | "begin": "@\/", 266 | "beginCaptures": [ 267 | { 268 | "name": "punctuation.definition.regexp.begin.jinja" 269 | } 270 | ], 271 | "end": "\/", 272 | "endCaptures": [ 273 | { 274 | "name": "punctuation.definition.regexp.end.jinja" 275 | } 276 | ], 277 | "name": "string.regexp.jinja", 278 | "patterns": [ 279 | { 280 | "include": "#simple_escapes" 281 | } 282 | ] 283 | } 284 | ] 285 | }, 286 | "simple_escapes": { 287 | "captures": { 288 | "1": { 289 | "name": "constant.character.escape.newline.jinja" 290 | }, 291 | "10": { 292 | "name": "constant.character.escape.tab.jinja" 293 | }, 294 | "11": { 295 | "name": "constant.character.escape.vertical-tab.jinja" 296 | }, 297 | "2": { 298 | "name": "constant.character.escape.backlash.jinja" 299 | }, 300 | "3": { 301 | "name": "constant.character.escape.double-quote.jinja" 302 | }, 303 | "4": { 304 | "name": "constant.character.escape.single-quote.jinja" 305 | }, 306 | "5": { 307 | "name": "constant.character.escape.bell.jinja" 308 | }, 309 | "6": { 310 | "name": "constant.character.escape.backspace.jinja" 311 | }, 312 | "7": { 313 | "name": "constant.character.escape.formfeed.jinja" 314 | }, 315 | "8": { 316 | "name": "constant.character.escape.linefeed.jinja" 317 | }, 318 | "9": { 319 | "name": "constant.character.escape.return.jinja" 320 | } 321 | }, 322 | "match": "(\\\\\\n)|(\\\\\\\\)|(\\\\\\\")|(\\\\')|(\\\\a)|(\\\\b)|(\\\\f)|(\\\\n)|(\\\\r)|(\\\\t)|(\\\\v)" 323 | }, 324 | "string": { 325 | "patterns": [ 326 | { 327 | "include": "#simple_escapes" 328 | }, 329 | { 330 | "include": "#escaped_char" 331 | }, 332 | { 333 | "include": "#escaped_unicode_char" 334 | } 335 | ] 336 | } 337 | } 338 | } --------------------------------------------------------------------------------