{{ item.title }}
\n\t\t\n\t\t{{ item.date }}
\n\n\t\t{{ item.summary }}\n\t├── images └── icon.png ├── .github └── FUNDING.yml ├── .gitattributes ├── .vscode ├── settings.json ├── extensions.json └── launch.json ├── .vscodeignore ├── src ├── languages │ └── twig.configuration.json ├── hover │ ├── functions.json │ ├── twig.json │ └── filters.json ├── extension.js ├── snippets │ └── snippets.json └── syntaxes │ └── twig.tmLanguage ├── .gitignore ├── .eslintrc.json ├── LICENSE.md ├── rollup.config.js ├── CHANGELOG.md ├── README.md ├── package.json └── extension └── index.js /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mblode/vscode-twig-language/HEAD/images/icon.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [mblode] 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": true, 3 | "vscode-journal-view.expanded": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | test/** 4 | .gitignore 5 | jsconfig.json 6 | vsc-extension-quickstart.md 7 | .eslintrc.json 8 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/languages/twig.configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "blockComment": [ "{#", "#}" ] 4 | }, 5 | "brackets": [ 6 | ["{{", "}}"], 7 | ["{%", "%}"], 8 | ["[", "]"], 9 | ["(", ")"] 10 | ], 11 | "surroundingPairs": [ 12 | { "open": "'", "close": "'" }, 13 | { "open": "\"", "close": "\"" }, 14 | { "open": "{{", "close": "}}"}, 15 | { "open": "{%", "close": "%}"}, 16 | { "open": "[", "close": "]"}, 17 | { "open": "(", "close": ")" }, 18 | { "open": "<", "close": ">" } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode-test/ 3 | *.vsix 4 | 5 | ### OSX ### 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": false, 4 | "commonjs": true, 5 | "es6": true, 6 | "node": true 7 | }, 8 | "parserOptions": { 9 | "ecmaFeatures": { 10 | "jsx": true 11 | }, 12 | "sourceType": "module" 13 | }, 14 | "rules": { 15 | "no-const-assign": "warn", 16 | "no-this-before-super": "warn", 17 | "no-undef": "warn", 18 | "no-unreachable": "warn", 19 | "no-unused-vars": "warn", 20 | "constructor-super": "warn", 21 | "valid-typeof": "warn" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ] 16 | }, 17 | { 18 | "name": "Extension Tests", 19 | "type": "extensionHost", 20 | "request": "launch", 21 | "runtimeExecutable": "${execPath}", 22 | "args": [ 23 | "--extensionDevelopmentPath=${workspaceFolder}", 24 | "--extensionTestsPath=${workspaceFolder}/test" 25 | ] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 mblode 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 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import json from 'rollup-plugin-json'; 2 | 3 | export default [ 4 | { 5 | input: 'src/extension.js', 6 | output: { 7 | file: 'extension/index.js', 8 | format: 'cjs' 9 | }, 10 | plugins: [ 11 | json({ 12 | // All JSON files will be parsed by default, 13 | // but you can also specifically include/exclude files 14 | exclude: ['node_modules/**'], 15 | 16 | // for tree-shaking, properties will be declared as 17 | // variables, using either `var` or `const` 18 | preferConst: true, // Default: false 19 | 20 | // specify indentation for the generated default export — 21 | // defaults to '\t' 22 | indent: ' ', 23 | 24 | // ignores indent and generates the smallest code 25 | compact: true, // Default: false 26 | 27 | // generate a named export for every property of the JSON object 28 | namedExports: true // Default: true 29 | }) 30 | ] 31 | }, 32 | ] 33 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## [0.8.0] - 2019-04-17 6 | 7 | ### Changed 8 | 9 | - Pretty Diff formatting bug has been solved correctly 10 | 11 | ### Added 12 | 13 | - Added many more configuration options 14 | 15 | ## [0.7.0] - 2019-04-01 16 | 17 | ### Changed 18 | 19 | - Fixed bug that clears entire document and only leaves the script tag 20 | - Preserved new lines 21 | - Updated packages 22 | - Converted extension to ES6 23 | 24 | ## [0.6.0] - 2019-02-26 25 | 26 | ### Changed 27 | 28 | - Updated snippets for Craft CMS 3 29 | 30 | ## [0.5.1] - 2019-01-31 31 | 32 | ## Added 33 | 34 | - Add changelog (finally) 35 | 36 | ### Changed 37 | 38 | - Update Prettydiff package to 100.1.7 39 | 40 | ## [0.4.4] - 2019-01-05 41 | 42 | ### Changed 43 | 44 | - Move to Pretty Diff 3 45 | - Clean up package.json 46 | - Refactor format selection based on Unibeautify and Prettier 47 | - Fix extension settings to match Pretty Diff 3's option changes 48 | - Fix tab size issue 49 | - Update readme to be more clear about limitations of the extension 50 | 51 | ## [0.3.2] - 2018-04-02 52 | 53 | ### Changed 54 | 55 | - Fix issues with snippes 56 | - Refine readme documentation 57 | 58 | ## [0.2.11] - 2018-01-20 59 | 60 | ### Added 61 | 62 | - Option to disable formatter 63 | 64 | ### Changed 65 | 66 | - Experiment with activation events 67 | - Fix configuration options 68 | 69 | ## [0.1.5] - 2017-11-13 70 | 71 | ### Added 72 | 73 | - Add options for configuration in VS Code 74 | - Format selection functionality 75 | - Add Prettty Diff 2 as an NPM package 76 | - Create hover features for VS Code 77 | 78 | ### Changed 79 | 80 | - Update readme 81 | - Fix gitignore 82 | - Change extension.js to add configuration to Pretty Diff 83 | 84 | ### Removed 85 | 86 | - Remove Pretty Diff 2 as a library 87 | 88 | ## [0.1.1] - 2017-11-12 89 | 90 | ### Added 91 | 92 | - Create a comprehensive readme file 93 | - Initial changelog 94 | - Add Craft/Twig snippets 95 | - Syntax highlighting for twig files 96 | - Initialise VS Code extension using Yeoman 97 | - Add icon for Twig Language extension 98 | - Use Pretty Diff 2 as the primary Twig formatter 99 | - Create extension.js file 100 | -------------------------------------------------------------------------------- /src/hover/functions.json: -------------------------------------------------------------------------------- 1 | { 2 | "attribute": { 3 | "prefix": "attribute", 4 | "body": "{{ attribute($1) }}$2", 5 | "description": 6 | "The attribute function can be used to access a \"dynamic\" attribute of a variable", 7 | "example": "" 8 | }, 9 | "block": { 10 | "prefix": "block", 11 | "body": "{{ block('${block name}') }}$1", 12 | "description": 13 | "When a template uses inheritance and if you want to print a block multiple times, use the block function", 14 | "example": "" 15 | }, 16 | "constant": { 17 | "prefix": "constant", 18 | "body": "{{ constant('${const name}') }}$1", 19 | "description": "constant returns the constant value for a given string", 20 | "example": 21 | "{{ some_date | date(constant('DATE_W3C')) }}\n{{ constant('Namespace\\Classname::CONSTANT_NAME') }}" 22 | }, 23 | "cycle": { 24 | "prefix": "cycle", 25 | "body": "{{ cycle(${array}, ${position}) }}$1", 26 | "description": "The cycle function cycles on an array of values", 27 | "example": "" 28 | }, 29 | "date": { 30 | "prefix": "date", 31 | "body": "{% set ${currentDate} = date($1) %}$2", 32 | "description": 33 | "Converts an argument to a date to allow date comparison", 34 | "example": 35 | "{% date() %}\n{% date('-2days') %}\n{% date('-2days', 'Europe/Paris') %}" 36 | }, 37 | "dump": { 38 | "prefix": "dump", 39 | "body": "{{ dump(${array}) }}$1", 40 | "description": 41 | "(function) dumps information about a template variable. This is mostly useful to debug a template that does not behave as expected by introspecting its variables", 42 | "example": "" 43 | }, 44 | "include": { 45 | "prefix": "include function", 46 | "body": "{{ include('${filename}.twig') }}$1", 47 | "description": "(function) returns the rendered content of a template", 48 | "example": "" 49 | }, 50 | "max": { 51 | "prefix": "max", 52 | "body": "{% set ${result} = max(${array}) %}$1", 53 | "description": 54 | "(function) returns the biggest value of a sequence or a set of values", 55 | "example": 56 | "{{ max(1, 3, 2) }}\n{# returns \"3\" #}\n\n{{ max({2: \"e\", 3: \"a\", 1: \"b\", 5: \"d\", 4: \"c\"}) }}\n{# returns \"e\" #}" 57 | }, 58 | "min": { 59 | "prefix": "min", 60 | "body": "{% set ${result} = min(${array}) %}$1", 61 | "description": 62 | "(function) returns the lowest value of a sequence or a set of values", 63 | "example": 64 | "{{ min(1, 3, 2) }}\n{# returns \"1\" #}\n\n{{ min({2: \"e\", 3: \"a\", 1: \"b\", 5: \"d\", 4: \"c\"}) }}\n{# returns \"a\" #}" 65 | }, 66 | "parent": { 67 | "prefix": "parent", 68 | "body": "{{ parent() }}", 69 | "description": 70 | "(function) return the content of the block as defined in the base template", 71 | "example": 72 | "{% extends \"base.html\" %}\n\n{% block sidebar %}\n\t
{{ dump() }}{% exit %}
145 | dump {{ dump() }}
146 | ```
147 |
148 | ### Example Forms
149 |
150 | ```twig
151 |
152 | formlogin Example login form
153 | formuserprofile Example user profile form
154 | formuserregistration Example user registration form
155 | formforgotpassword Example forgot password form
156 | formsetpassword Example set password form
157 | formsearch Example search form
158 | formsearchresults Example search form results
159 |
160 | ```
161 |
162 | ### Reference Hints
163 |
164 | ```twig
165 |
166 | info All craft.assets properties and template tags
167 | info All craft.crategories properties and template tags
168 | info All craft.config properties and template tags
169 | info All craft.entries properties and template tags
170 | info All craft.feeds properties and template tags
171 | info All craft.fields properties and template tags
172 | info All craft.globals properties and template tags
173 | info All craft.request properties and template tags
174 | info All craft.sections properties and template tags
175 | info All craft.session properties and template tags
176 | info All craft.tags properties and template tags
177 | info All craft.users properties and template tags
178 | info All craft globals (site info, date, users, template tags)
179 |
180 | ```
181 |
--------------------------------------------------------------------------------
/src/hover/twig.json:
--------------------------------------------------------------------------------
1 | {
2 | "show": {
3 | "prefix": "show",
4 | "body": "{{ $1 }}",
5 | "description": "{{ }}"
6 | },
7 | "execute": {
8 | "prefix": "execute",
9 | "body": "{% $1 %}",
10 | "description": "{% %}"
11 | },
12 | "autoescape": {
13 | "prefix": "autoescape",
14 | "body": ["{% autoescape %}", "\t$1", "{% endautoescape %}"],
15 | "description":
16 | "Whether automatic escaping is enabled or not, you can mark a section of a template to be escaped or not by using the autoescape tag",
17 | "example":
18 | "{% autoescape %}\n Everything will be automatically escaped in this block\n using the HTML strategy\n{% endautoescape %}\n\n{% autoescape 'html' %}\n Everything will be automatically escaped in this block\n using the HTML strategy\n{% endautoescape %}\n\n{% autoescape 'js' %}\n Everything will be automatically escaped in this block\n using the js escaping strategy\n{% endautoescape %}\n\n{% autoescape false %}\n Everything will be outputted as is in this block\n{% endautoescape %}"
19 | },
20 | "block": {
21 | "prefix": "block",
22 | "body": ["{% block ${name} %}", "\t$1", "{% endblock ${name} %}"],
23 | "description":
24 | "When a template uses inheritance and if you want to print a block multiple times, use the block function"
25 | },
26 | "do": {
27 | "prefix": "do",
28 | "body": ["{% do $1 %}"],
29 | "description":
30 | "The do tag works exactly like the regular variable expression ({{ ... }}) just that it doesn't print anything",
31 | "example": "{% do 1 + 2 %}"
32 | },
33 | "embed": {
34 | "prefix": "embed",
35 | "body": ["{% embed \"${filename}.twig\" %}", "\t$1", "{% endembed %}"],
36 | "description":
37 | "The embed tag combines the behaviour of include and extends. It allows you to include another template's contents, just like include does. But it also allows you to override any block defined inside the included template, like when extending a template"
38 | },
39 | "extends": {
40 | "prefix": "extends",
41 | "body": "{% extends \"${filename}.twig\" %}",
42 | "description": "Twig snippets"
43 | },
44 | "filter": {
45 | "prefix": "filter",
46 | "body": ["{% filter ${filter name} %}", "\t$1", "{% endfilter %}"],
47 | "description":
48 | "Filter sections allow you to apply regular Twig filters on a block of template data. Just wrap the code in the special filter section",
49 | "example":
50 | "{% filter lower | escape %}\n SOME TEXT\n{% endfilter %}\n\n{# outputs \"<strong>some text</strong>\" #}"
51 | },
52 | "flush": {
53 | "prefix": "flush",
54 | "body": ["{% flush %}"],
55 | "description": "The flush tag tells Twig to flush the output buffer",
56 | "example": "{% flush %}"
57 | },
58 | "for": {
59 | "prefix": "for",
60 | "body": ["{% for ${row} in ${array} %}", "\t$1", "{% endfor %}"],
61 | "description": "Loop over each item in a sequence"
62 | },
63 | "for if": {
64 | "prefix": "for if",
65 | "body": [
66 | "{% for ${row} in ${array} if ${condition} %}",
67 | "\t$1",
68 | "{% endfor %}"
69 | ],
70 | "description": "Loop over each item in a sequence"
71 | },
72 | "for else": {
73 | "prefix": "for else",
74 | "body": [
75 | "{% for ${row} in ${array} %}",
76 | "\t$1",
77 | "{% else %}",
78 | "\t$2",
79 | "{% endfor %}"
80 | ],
81 | "description": "Loop over each item in a sequence"
82 | },
83 | "for if else": {
84 | "prefix": "for if else",
85 | "body": [
86 | "{% for ${row} in ${array} if ${condition} %}",
87 | "\t$1",
88 | "{% else %}",
89 | "\t$2",
90 | "{% endfor %}"
91 | ],
92 | "description": "Loop over each item in a sequence"
93 | },
94 | "loop": {
95 | "prefix": "loop",
96 | "body": "loop.",
97 | "description": "special variables inside of a for loop block"
98 | },
99 | "if": {
100 | "prefix": "if",
101 | "body": ["{% if ${condition} %}", "\t$1", "{% endif %}"],
102 | "description":
103 | "The if statement in Twig is comparable with the if statements of PHP"
104 | },
105 | "if else": {
106 | "prefix": "if else",
107 | "body": [
108 | "{% if ${condition} %}",
109 | "\t$1",
110 | "{% else %}",
111 | "\t$2",
112 | "{% endif %}"
113 | ],
114 | "description":
115 | "The if statement in Twig is comparable with the if statements of PHP"
116 | },
117 | "else": {
118 | "prefix": "else",
119 | "body": "{% else %}",
120 | "description":
121 | "The if statement in Twig is comparable with the if statements of PHP"
122 | },
123 | "else if": {
124 | "prefix": "else if",
125 | "body": "{% elseif ${condition} %}",
126 | "description":
127 | "The if statement in Twig is comparable with the if statements of PHP"
128 | },
129 | "import": {
130 | "prefix": "import",
131 | "body": "{% import \"${filename}.twig\" as ${alias}%}",
132 | "description":
133 | "Twig supports putting often used code into macros. These macros can go into different templates and get imported from there."
134 | },
135 | "_self": {
136 | "prefix": "_self",
137 | "body": "_self",
138 | "description":
139 | "To import macros from the current file, use the special _self variable for the source"
140 | },
141 | "include": {
142 | "prefix": "include",
143 | "body": "{% include \"${filename}.twig\" %}",
144 | "description":
145 | "The include statement includes a template and returns the rendered content of that file into the current namespace"
146 | },
147 | "macro": {
148 | "prefix": "macro",
149 | "body": ["{% macro ${name}($1) %}", "\t$2", "{% endmacro %}"],
150 | "description": "Twig snippets"
151 | },
152 | "sandbox": {
153 | "prefix": "sandbox",
154 | "body": ["{% sandbox %}", "\t$1", "{% endsandbox %}"],
155 | "description":
156 | "The sandbox tag can be used to enable the sandboxing mode for an included template, when sandboxing is not enabled globally for the Twig environment"
157 | },
158 | "set": {
159 | "prefix": "set",
160 | "body": ["{% set ${name} = ${value} %}$1"],
161 | "description": "Assign values to variables"
162 | },
163 | "set block": {
164 | "prefix": "set (block)",
165 | "body": ["{% set ${name} %}", "\t$1", "{% endset %}"],
166 | "description":
167 | "Inside code blocks you can also assign values to variables. Assignments use the set tag and can have multiple targets"
168 | },
169 | "spaceless": {
170 | "prefix": "spaceless",
171 | "body": ["{% spaceless %}", "\t$1", "{% endspaceless %}"],
172 | "description":
173 | "Use the spaceless tag to remove whitespace between HTML tags, not whitespace within HTML tags or whitespace in plain text"
174 | },
175 | "use": {
176 | "prefix": "use",
177 | "body": "{% use \"${filename}.twig\" %}",
178 | "description": "Twig snippets"
179 | },
180 | "verbatim": {
181 | "prefix": "verbatim",
182 | "body": ["{% verbatim %}", "\t$1", "{% endverbatim %}"],
183 | "description":
184 | "The verbatim tag marks sections as being raw text that should not be parsed. For example to put Twig syntax as example into a template you can use this snippet"
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/src/hover/filters.json:
--------------------------------------------------------------------------------
1 | {
2 | "abs": {
3 | "text": "abs",
4 | "body": "abs",
5 | "description": "filter returns the absolute value"
6 | },
7 | "batch": {
8 | "prefix": "batch",
9 | "body": "batch(${size}, ${fill})",
10 | "text": "batch(size, fill)",
11 | "description":
12 | "filter \"batches\" items by returning a list of lists with the given number of items. A second parameter can be provided and used to fill in missing items"
13 | },
14 | "capitalize": {
15 | "text": "capitalize",
16 | "body": "capitalize",
17 | "description":
18 | "filter capitalizes a value. The first character will be uppercase, all others lowercase"
19 | },
20 | "convert_encoding": {
21 | "prefix": "convert_encoding",
22 | "body": "convert_encoding('${to}', '${from}')",
23 | "text": "convert_encoding('to', 'from')",
24 | "description":
25 | "filter converts a string from one encoding to another. The first argument is the expected output charset and the second one is the input charset"
26 | },
27 | "date": {
28 | "prefix": "date",
29 | "body": "date(\"${m/d/Y}\")",
30 | "text": "date(\"m/d/Y\")",
31 | "description": "filter formats a date to a given format"
32 | },
33 | "date_modify": {
34 | "prefix": "date_modify",
35 | "body": "date_modify(\"${+1 day}\")",
36 | "text": "date_modify(\"+1 day\")",
37 | "description": "filter modifies a date with a given modifier string"
38 | },
39 | "default": {
40 | "prefix": "default",
41 | "body": "default('${default value}')",
42 | "text": "default('default value')",
43 | "description":
44 | "filter returns the passed default value if the value is undefined or empty, otherwise the value of the variable"
45 | },
46 | "escape": {
47 | "text": "escape",
48 | "body": "escape",
49 | "description":
50 | "filter escapes a string for safe insertion into the final output. It supports different escaping strategies depending on the template context"
51 | },
52 | "first": {
53 | "text": "first",
54 | "body": "first",
55 | "description":
56 | "filter returns the first \"element\" of a sequence, a mapping, or a string"
57 | },
58 | "format": {
59 | "prefix": "format",
60 | "body": "format($1)",
61 | "text": "format()",
62 | "description":
63 | "filter formats a given string by replacing the placeholders (placeholders follows the sprintf notation)",
64 | "example":
65 | "{% set foo = \"foo\" %}\n{{ \"I like %s and %s.\"| format(foo, \"bar\") }}\n\n{# outputs I like foo and bar #}"
66 | },
67 | "join": {
68 | "prefix": "join",
69 | "body": "join${('optional')}",
70 | "text": "join",
71 | "description":
72 | "filter returns a string which is the concatenation of the items of a sequence"
73 | },
74 | "json_encode": {
75 | "prefix": "json_encode",
76 | "body": "json_encode()",
77 | "text": "json_encode()",
78 | "description":
79 | "filter returns the JSON representation of a value. Internally, Twig uses the PHP json_encode function."
80 | },
81 | "keys": {
82 | "text": "keys",
83 | "body": "keys",
84 | "description":
85 | "filter returns the keys of an array. It is useful when you want to iterate over the keys of an array"
86 | },
87 | "last": {
88 | "text": "last",
89 | "body": "last",
90 | "description":
91 | "filter returns the last \"element\" of a sequence, a mapping, or a string"
92 | },
93 | "length": {
94 | "text": "length",
95 | "body": "length",
96 | "description":
97 | "filter returns the number of items of a sequence or mapping, or the length of a string"
98 | },
99 | "lower": {
100 | "text": "lower",
101 | "body": "lower",
102 | "description": "filter converts a value to lowercase"
103 | },
104 | "merge": {
105 | "prefix": "merge",
106 | "body": "merge(${array})",
107 | "text": "merge(array)",
108 | "description": "filter merges an array with another array"
109 | },
110 | "nl2br": {
111 | "text": "nl2br",
112 | "body": "nl2br",
113 | "description":
114 | "filter inserts HTML line breaks before all newlines in a string"
115 | },
116 | "number_format": {
117 | "prefix": "number_format",
118 | "body": "number_format(${0}, '${.}', '${,}')",
119 | "text": "number_format",
120 | "description":
121 | "filter formats numbers. It is a wrapper around PHP's number_format function"
122 | },
123 | "raw": {
124 | "text": "raw",
125 | "body": "raw",
126 | "description":
127 | "filter marks the value as being \"safe\", which means that in an environment with automatic escaping enabled this variable will not be escaped if raw is the last filter applied to it."
128 | },
129 | "replace": {
130 | "prefix": "replace",
131 | "body": "replace('${search}' : '${replace}')",
132 | "text": "replace('search' : 'replace')",
133 | "description":
134 | "filter formats a given string by replacing the placeholders."
135 | },
136 | "reverse": {
137 | "text": "reverse",
138 | "body": "reverse",
139 | "description": "filter reverses a sequence, a mapping, or a string"
140 | },
141 | "round": {
142 | "prefix": "round",
143 | "body": "${0} | round(1, '${floor}')",
144 | "text": "round",
145 | "description": "filter rounds a number to a given precision"
146 | },
147 | "slice": {
148 | "prefix": "slice",
149 | "body": "slice(${start}, ${length})",
150 | "text": "slice(start, length)",
151 | "description":
152 | "filter extracts a slice of a sequence, a mapping, or a string"
153 | },
154 | "slice [] notation": {
155 | "prefix": "slice [] notation",
156 | "body": "[${start}:${length}]",
157 | "description":
158 | "filter extracts a slice of a sequence, a mapping, or a string"
159 | },
160 | "sort": {
161 | "text": "sort",
162 | "body": "sort",
163 | "description": "filter sorts an array"
164 | },
165 | "split": {
166 | "prefix": "split",
167 | "body": "split('$1')",
168 | "text": "split('')",
169 | "description":
170 | "filter splits a string by the given delimiter and returns a list of strings"
171 | },
172 | "striptags": {
173 | "text": "striptags",
174 | "body": "striptags",
175 | "description":
176 | "filter strips SGML/XML tags and replace adjacent whitespace by one space"
177 | },
178 | "title": {
179 | "text": "title",
180 | "body": "title",
181 | "description":
182 | "filter returns a titlecased version of the value. Words will start with uppercase letters, all remaining characters are lowercase"
183 | },
184 | "trim": {
185 | "text": "trim",
186 | "body": "trim",
187 | "description":
188 | "filter strips whitespace (or other characters) from the beginning and end of a string"
189 | },
190 | "trim()": {
191 | "prefix": "trim()",
192 | "body": "trim('$1')",
193 | "description":
194 | "filter strips whitespace (or other characters) from the beginning and end of a string"
195 | },
196 | "upper": {
197 | "text": "upper",
198 | "body": "upper",
199 | "description": "filter converts a value to uppercase"
200 | },
201 | "url_encode": {
202 | "text": "url_encode",
203 | "body": "url_encode",
204 | "description":
205 | "filter percent encodes a given string as URL segment or an array as query string"
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "twig-language",
3 | "displayName": "Twig Language",
4 | "description": "Snippets, Syntax Highlighting, Hover, and Formatting for Twig",
5 | "version": "0.9.4",
6 | "publisher": "mblode",
7 | "license": "MIT",
8 | "author": {
9 | "name": "Matthew Blode",
10 | "email": "m@blode.co",
11 | "url": "https://matthewblode.com"
12 | },
13 | "homepage": "https://github.com/mblode/vscode-twig-language",
14 | "bugs": {
15 | "url": "https://github.com/mblode/vscode-twig-language/issues"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/mblode/vscode-twig-language.git"
20 | },
21 | "icon": "images/icon.png",
22 | "engines": {
23 | "vscode": "^1.30.0"
24 | },
25 | "categories": [
26 | "Programming Languages",
27 | "Snippets",
28 | "Other"
29 | ],
30 | "keywords": [
31 | "php",
32 | "twig",
33 | "snippets",
34 | "craft",
35 | "beautify"
36 | ],
37 | "activationEvents": [
38 | "*"
39 | ],
40 | "main": "./extension/index",
41 | "contributes": {
42 | "languages": [
43 | {
44 | "id": "html",
45 | "aliases": [
46 | "HTML",
47 | "twig"
48 | ],
49 | "extensions": [
50 | ".twig",
51 | ".html",
52 | ".html.twig"
53 | ],
54 | "configuration": "./src/languages/twig.configuration.json"
55 | }
56 | ],
57 | "grammars": [
58 | {
59 | "language": "html",
60 | "scopeName": "text.html.twig",
61 | "path": "./src/syntaxes/twig.tmLanguage",
62 | "embeddedLanguages": {
63 | "source.json": "json",
64 | "source.css": "css",
65 | "source.css.scss": "scss",
66 | "source.js": "javascript",
67 | "source.ts": "typescript"
68 | }
69 | }
70 | ],
71 | "snippets": [
72 | {
73 | "language": "html",
74 | "path": "./src/snippets/snippets.json"
75 | }
76 | ],
77 | "configuration": {
78 | "type": "object",
79 | "title": "Twig Language",
80 | "properties": {
81 | "twig-language.hover": {
82 | "type": "boolean",
83 | "default": true,
84 | "description": "Whether to enable/disable Twig hover."
85 | },
86 | "twig-language.formatting": {
87 | "type": "boolean",
88 | "default": true,
89 | "description": "Whether to enable/disable Twig PrettyDiff formatting."
90 | },
91 | "twig-language.braceLine": {
92 | "type": "boolean",
93 | "default": false,
94 | "description": "If true an empty line will be inserted after opening curly braces and before closing curly braces."
95 | },
96 | "twig-language.bracePadding": {
97 | "type": "boolean",
98 | "default": false,
99 | "description": "Inserts a space after the start of a container and before the end of the container if the contents of that container are not indented; such as: conditions, function arguments, and escaped sequences of template strings."
100 | },
101 | "twig-language.braceStyle": {
102 | "type": "string",
103 | "enum": [
104 | "collapse",
105 | "collapse-preserve-inline",
106 | "expand",
107 | "none"
108 | ],
109 | "default": "none",
110 | "description": "Emulates JSBeautify's brace_style option using existing Pretty Diff options."
111 | },
112 | "twig-language.braces": {
113 | "type": "boolean",
114 | "default": false,
115 | "description": "Determines if opening curly braces will exist on the same line as their condition or be forced onto a new line."
116 | },
117 | "twig-language.commentLine": {
118 | "type": "boolean",
119 | "default": false,
120 | "description": "If a blank new line should be forced above comments."
121 | },
122 | "twig-language.comments": {
123 | "type": "boolean",
124 | "default": false,
125 | "description": "This will determine whether comments should always start at position 0 of each line or if comments should be indented according to the code."
126 | },
127 | "twig-language.compressedCss": {
128 | "type": "boolean",
129 | "default": false,
130 | "description": "If CSS should be beautified in a style where the properties and values are minifed for faster reading of selectors."
131 | },
132 | "twig-language.correct": {
133 | "type": "boolean",
134 | "default": false,
135 | "description": "Automatically correct some sloppiness in code."
136 | },
137 | "twig-language.cssInsertLines": {
138 | "type": "boolean",
139 | "default": false,
140 | "description": "Inserts new line characters between every CSS code block."
141 | },
142 | "twig-language.elseLine": {
143 | "type": "boolean",
144 | "default": false,
145 | "description": "If else_line is true then the keyword 'else' is forced onto a new line."
146 | },
147 | "twig-language.endComma": {
148 | "type": "string",
149 | "enum": [
150 | "always",
151 | "never",
152 | "none"
153 | ],
154 | "default": false,
155 | "description": "If there should be a trailing comma in arrays and objects. Value multiline only applies to modes beautify and diff."
156 | },
157 | "twig-language.forceAttribute": {
158 | "type": "boolean",
159 | "default": false,
160 | "description": "If all markup attributes should be indented each onto their own line."
161 | },
162 | "twig-language.forceIndent": {
163 | "type": "boolean",
164 | "default": false,
165 | "description": "Will force indentation upon all content and tags without regard for the creation of new text nodes."
166 | },
167 | "twig-language.formatArray": {
168 | "type": "string",
169 | "enum": [
170 | "default",
171 | "indent",
172 | "inline"
173 | ],
174 | "default": "default",
175 | "description": "Determines if all array indexes should be indented, never indented, or left to the default."
176 | },
177 | "twig-language.formatObject": {
178 | "type": "string",
179 | "enum": [
180 | "default",
181 | "indent",
182 | "inline"
183 | ],
184 | "default": "default",
185 | "description": "Determines if all object keys should be indented, never indented, or left to the default."
186 | },
187 | "twig-language.functionName": {
188 | "type": "boolean",
189 | "default": false,
190 | "description": "If a space should follow a JavaScript function name."
191 | },
192 | "twig-language.indentStyle": {
193 | "type": "string",
194 | "enum": [
195 | "space",
196 | "tab"
197 | ],
198 | "default": "tab",
199 | "description": "Choose to indent using tabs or spaces."
200 | },
201 | "twig-language.indentLevel": {
202 | "type": "integer",
203 | "default": 0,
204 | "description": "How much indentation padding should be applied to beautification? This option is internally used for code that requires switching between libraries."
205 | },
206 | "twig-language.tabSize": {
207 | "type": "integer",
208 | "default": 0,
209 | "description": "0 will default to the editor's tab size. Stores the number of 'inchar' values to comprise a single indentation."
210 | },
211 | "twig-language.methodChain": {
212 | "type": "integer",
213 | "default": 0,
214 | "description": "When to break consecutively chained methods and properties onto separate lines. A negative value disables this option. A value of 0 ensures method chains are never broken."
215 | },
216 | "twig-language.neverFlatten": {
217 | "type": "boolean",
218 | "default": false,
219 | "description": "If destructured lists in script should never be flattend."
220 | },
221 | "twig-language.newLine": {
222 | "type": "boolean",
223 | "default": true,
224 | "description": "Insert an empty line at the end of output."
225 | },
226 | "twig-language.noCaseIndent": {
227 | "type": "boolean",
228 | "default": false,
229 | "description": "If a case statement should receive the same indentation as the containing switch block."
230 | },
231 | "twig-language.noLeadZero": {
232 | "type": "boolean",
233 | "default": false,
234 | "description": "Whether leading 0s in CSS values immediately preceeding a decimal should be removed or prevented."
235 | },
236 | "twig-language.objectSort": {
237 | "type": "boolean",
238 | "default": false,
239 | "description": "Sorts markup attributes and properties by key name in script and style."
240 | },
241 | "twig-language.preserve": {
242 | "type": "integer",
243 | "default": 2,
244 | "description": "The maximum number of consecutive empty lines to retain."
245 | },
246 | "twig-language.preserveComment": {
247 | "type": "boolean",
248 | "default": false,
249 | "description": "Prevent comment reformatting due to option wrap."
250 | },
251 | "twig-language.quoteConvert": {
252 | "type": "string",
253 | "enum": [
254 | "double",
255 | "none",
256 | "single"
257 | ],
258 | "default": "none",
259 | "description": "If the quotes of script strings or markup attributes should be converted to single quotes or double quotes."
260 | },
261 | "twig-language.space": {
262 | "type": "boolean",
263 | "default": true,
264 | "description": "Inserts a space following the function keyword for anonymous functions."
265 | },
266 | "twig-language.spaceClose": {
267 | "type": "boolean",
268 | "default": false,
269 | "description": "Markup self-closing tags end will end with ' />' instead of '/>'."
270 | },
271 | "twig-language.tagMerge": {
272 | "type": "boolean",
273 | "default": false,
274 | "description": "Allows immediately adjacement start and end markup tags of the same name to be combined into a single self-closing tag."
275 | },
276 | "twig-language.tagSort": {
277 | "type": "boolean",
278 | "default": false,
279 | "description": "Sort child items of each respective markup parent element."
280 | },
281 | "twig-language.ternaryLine": {
282 | "type": "boolean",
283 | "default": true,
284 | "description": "If ternary operators in JavaScript ? and : should remain on the same line."
285 | },
286 | "twig-language.unformatted": {
287 | "type": "boolean",
288 | "default": false,
289 | "description": "If markup tags should have their insides preserved. This option is only available to markup and does not support child tokens that require a different lexer."
290 | },
291 | "twig-language.variableList": {
292 | "type": "string",
293 | "enum": [
294 | "each",
295 | "list",
296 | "none"
297 | ],
298 | "default": "none",
299 | "description": "If consecutive JavaScript variables should be merged into a comma separated list or if variables in a list should be separated."
300 | },
301 | "twig-language.vertical": {
302 | "type": "boolean",
303 | "default": false,
304 | "description": "If lists of assignments and properties should be vertically aligned. This option is not used with the markup lexer."
305 | },
306 | "twig-language.wrap": {
307 | "type": "integer",
308 | "default": 0,
309 | "description": "Character width limit before applying word wrap. A 0 value disables this option. A negative value concatenates script strings."
310 | }
311 | }
312 | }
313 | },
314 | "capabilities": {
315 | "hoverProvider": "true"
316 | },
317 | "scripts": {
318 | "start": "rollup -c",
319 | "build": "rollup -c",
320 | "watch": "rollup -c -w"
321 | },
322 | "devDependencies": {
323 | "@types/mocha": "^8.0.3",
324 | "@types/node": "^14.6.0",
325 | "eslint": "^7.7.0",
326 | "eslint-config-prettier": "^6.11.0",
327 | "typescript": "^4.0.2",
328 | "vscode": "^1.1.37"
329 | },
330 | "dependencies": {
331 | "prettydiff": "^101.2.6",
332 | "rollup": "^2.26.5",
333 | "rollup-plugin-babel": "^4.4.0",
334 | "rollup-plugin-json": "^4.0.0"
335 | }
336 | }
337 |
--------------------------------------------------------------------------------
/extension/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var vscode = require('vscode');
4 | var prettydiff = require('prettydiff');
5 |
6 | function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
7 |
8 | var vscode__default = /*#__PURE__*/_interopDefaultLegacy(vscode);
9 | var prettydiff__default = /*#__PURE__*/_interopDefaultLegacy(prettydiff);
10 |
11 | const abs={text:"abs",body:"abs",description:"filter returns the absolute value"};const batch={prefix:"batch",body:"batch(${size}, ${fill})",text:"batch(size, fill)",description:"filter \"batches\" items by returning a list of lists with the given number of items. A second parameter can be provided and used to fill in missing items"};const capitalize={text:"capitalize",body:"capitalize",description:"filter capitalizes a value. The first character will be uppercase, all others lowercase"};const convert_encoding={prefix:"convert_encoding",body:"convert_encoding('${to}', '${from}')",text:"convert_encoding('to', 'from')",description:"filter converts a string from one encoding to another. The first argument is the expected output charset and the second one is the input charset"};const date={prefix:"date",body:"date(\"${m/d/Y}\")",text:"date(\"m/d/Y\")",description:"filter formats a date to a given format"};const date_modify={prefix:"date_modify",body:"date_modify(\"${+1 day}\")",text:"date_modify(\"+1 day\")",description:"filter modifies a date with a given modifier string"};const first={text:"first",body:"first",description:"filter returns the first \"element\" of a sequence, a mapping, or a string"};const format={prefix:"format",body:"format($1)",text:"format()",description:"filter formats a given string by replacing the placeholders (placeholders follows the sprintf notation)",example:"{% set foo = \"foo\" %}\n{{ \"I like %s and %s.\"| format(foo, \"bar\") }}\n\n{# outputs I like foo and bar #}"};const join={prefix:"join",body:"join${('optional')}",text:"join",description:"filter returns a string which is the concatenation of the items of a sequence"};const json_encode={prefix:"json_encode",body:"json_encode()",text:"json_encode()",description:"filter returns the JSON representation of a value. Internally, Twig uses the PHP json_encode function."};const keys={text:"keys",body:"keys",description:"filter returns the keys of an array. It is useful when you want to iterate over the keys of an array"};const last={text:"last",body:"last",description:"filter returns the last \"element\" of a sequence, a mapping, or a string"};const length={text:"length",body:"length",description:"filter returns the number of items of a sequence or mapping, or the length of a string"};const lower={text:"lower",body:"lower",description:"filter converts a value to lowercase"};const merge={prefix:"merge",body:"merge(${array})",text:"merge(array)",description:"filter merges an array with another array"};const nl2br={text:"nl2br",body:"nl2br",description:"filter inserts HTML line breaks before all newlines in a string"};const number_format={prefix:"number_format",body:"number_format(${0}, '${.}', '${,}')",text:"number_format",description:"filter formats numbers. It is a wrapper around PHP's number_format function"};const raw={text:"raw",body:"raw",description:"filter marks the value as being \"safe\", which means that in an environment with automatic escaping enabled this variable will not be escaped if raw is the last filter applied to it."};const replace={prefix:"replace",body:"replace('${search}' : '${replace}')",text:"replace('search' : 'replace')",description:"filter formats a given string by replacing the placeholders."};const reverse={text:"reverse",body:"reverse",description:"filter reverses a sequence, a mapping, or a string"};const round={prefix:"round",body:"${0} | round(1, '${floor}')",text:"round",description:"filter rounds a number to a given precision"};const slice={prefix:"slice",body:"slice(${start}, ${length})",text:"slice(start, length)",description:"filter extracts a slice of a sequence, a mapping, or a string"};const sort={text:"sort",body:"sort",description:"filter sorts an array"};const split={prefix:"split",body:"split('$1')",text:"split('')",description:"filter splits a string by the given delimiter and returns a list of strings"};const striptags={text:"striptags",body:"striptags",description:"filter strips SGML/XML tags and replace adjacent whitespace by one space"};const title={text:"title",body:"title",description:"filter returns a titlecased version of the value. Words will start with uppercase letters, all remaining characters are lowercase"};const trim={text:"trim",body:"trim",description:"filter strips whitespace (or other characters) from the beginning and end of a string"};const upper={text:"upper",body:"upper",description:"filter converts a value to uppercase"};const url_encode={text:"url_encode",body:"url_encode",description:"filter percent encodes a given string as URL segment or an array as query string"};var snippetsArr = {abs:abs,batch:batch,capitalize:capitalize,convert_encoding:convert_encoding,date:date,date_modify:date_modify,"default": {prefix:"default",body:"default('${default value}')",text:"default('default value')",description:"filter returns the passed default value if the value is undefined or empty, otherwise the value of the variable"},"escape": {text:"escape",body:"escape",description:"filter escapes a string for safe insertion into the final output. It supports different escaping strategies depending on the template context"},first:first,format:format,join:join,json_encode:json_encode,keys:keys,last:last,length:length,lower:lower,merge:merge,nl2br:nl2br,number_format:number_format,raw:raw,replace:replace,reverse:reverse,round:round,slice:slice,"slice [] notation": {prefix:"slice [] notation",body:"[${start}:${length}]",description:"filter extracts a slice of a sequence, a mapping, or a string"},sort:sort,split:split,striptags:striptags,title:title,trim:trim,"trim()": {prefix:"trim()",body:"trim('$1')",description:"filter strips whitespace (or other characters) from the beginning and end of a string"},upper:upper,url_encode:url_encode};
12 |
13 | const attribute={prefix:"attribute",body:"{{ attribute($1) }}$2",description:"The attribute function can be used to access a \"dynamic\" attribute of a variable",example:""};const block={prefix:"block",body:"{{ block('${block name}') }}$1",description:"When a template uses inheritance and if you want to print a block multiple times, use the block function",example:""};const constant={prefix:"constant",body:"{{ constant('${const name}') }}$1",description:"constant returns the constant value for a given string",example:"{{ some_date | date(constant('DATE_W3C')) }}\n{{ constant('Namespace\\Classname::CONSTANT_NAME') }}"};const cycle={prefix:"cycle",body:"{{ cycle(${array}, ${position}) }}$1",description:"The cycle function cycles on an array of values",example:""};const date$1={prefix:"date",body:"{% set ${currentDate} = date($1) %}$2",description:"Converts an argument to a date to allow date comparison",example:"{% date() %}\n{% date('-2days') %}\n{% date('-2days', 'Europe/Paris') %}"};const dump={prefix:"dump",body:"{{ dump(${array}) }}$1",description:"(function) dumps information about a template variable. This is mostly useful to debug a template that does not behave as expected by introspecting its variables",example:""};const include={prefix:"include function",body:"{{ include('${filename}.twig') }}$1",description:"(function) returns the rendered content of a template",example:""};const max={prefix:"max",body:"{% set ${result} = max(${array}) %}$1",description:"(function) returns the biggest value of a sequence or a set of values",example:"{{ max(1, 3, 2) }}\n{# returns \"3\" #}\n\n{{ max({2: \"e\", 3: \"a\", 1: \"b\", 5: \"d\", 4: \"c\"}) }}\n{# returns \"e\" #}"};const min={prefix:"min",body:"{% set ${result} = min(${array}) %}$1",description:"(function) returns the lowest value of a sequence or a set of values",example:"{{ min(1, 3, 2) }}\n{# returns \"1\" #}\n\n{{ min({2: \"e\", 3: \"a\", 1: \"b\", 5: \"d\", 4: \"c\"}) }}\n{# returns \"a\" #}"};const parent={prefix:"parent",body:"{{ parent() }}",description:"(function) return the content of the block as defined in the base template",example:"{% extends \"base.html\" %}\n\n{% block sidebar %}\n\t{{ entries | length }} results:
\n\n\tYour search for “{{ query }}” didn’t return any results.
\n{% endif %}", 111 | "description": "craft.entries - example search results", 112 | "scope": "text.html.twig" 113 | }, 114 | "rss": { 115 | "prefix": "rss", 116 | "body": 117 | "\n{{ item.date }}
\n\n\t\t{{ item.summary }}\n\t\n\t{{ dump($1) }}\n\n{% exit %}$0",
221 | "description": "dump and die",
222 | "scope": "text.html.twig"
223 | },
224 | "do": {
225 | "prefix": "do",
226 | "body": "{% do $1 %}$0",
227 | "description": "do",
228 | "scope": "text.html.twig"
229 | },
230 | "dojs": {
231 | "prefix": "dojs",
232 | "body": "{% do view.registerJsFile \"${1:url}\" %}$0",
233 | "description": "do js",
234 | "scope": "text.html.twig"
235 | },
236 | "docss": {
237 | "prefix": "docss",
238 | "body": "{% do view.registerCssFile \"${1:url}\" %}$0",
239 | "description": "do css",
240 | "scope": "text.html.twig"
241 | },
242 | "dump": {
243 | "prefix": "dump",
244 | "body": "\n\t{{ dump($1) }}\n",
245 | "description": "dump",
246 | "scope": "text.html.twig"
247 | },
248 | "else": {
249 | "prefix": "else",
250 | "body": "{% else %}\n\t$0",
251 | "description": "else",
252 | "scope": "text.html.twig"
253 | },
254 | "embed": {
255 | "prefix": "embed",
256 | "body": "{% embed \"${1:template}\" %}\n\t$0\n{% endembed %}",
257 | "description": "embed",
258 | "scope": "text.html.twig"
259 | },
260 | "endautoescape": {
261 | "prefix": "endautoescape",
262 | "body": "{% endautoescape %}$0",
263 | "description": "endautoescape",
264 | "scope": "text.html.twig"
265 | },
266 | "endblock": {
267 | "prefix": "endblock",
268 | "body": "{% endblock %}$0",
269 | "description": "endblock",
270 | "scope": "text.html.twig"
271 | },
272 | "endcache": {
273 | "prefix": "endcache",
274 | "body": "{% endcache %}$0",
275 | "description": "endcache",
276 | "scope": "text.html.twig"
277 | },
278 | "endembed": {
279 | "prefix": "endembed",
280 | "body": "{% endembed %}$0",
281 | "description": "endembed",
282 | "scope": "text.html.twig"
283 | },
284 | "endfilter": {
285 | "prefix": "endfilter",
286 | "body": "{% endfilter %}$0",
287 | "description": "endfilter",
288 | "scope": "text.html.twig"
289 | },
290 | "endfor": {
291 | "prefix": "endfor",
292 | "body": "{% endfor %}$0",
293 | "description": "endfor",
294 | "scope": "text.html.twig"
295 | },
296 | "endif": {
297 | "prefix": "endif",
298 | "body": "{% endif %}$0",
299 | "description": "endif",
300 | "scope": "text.html.twig"
301 | },
302 | "endifchildren": {
303 | "prefix": "endifchildren",
304 | "body": "{% endifchildren %}$0",
305 | "description": "endifchildren",
306 | "scope": "text.html.twig"
307 | },
308 | "endcss": {
309 | "prefix": "endcss",
310 | "body": "{% endcss %}$0",
311 | "description": "endcss",
312 | "scope": "text.html.twig"
313 | },
314 | "endjs": {
315 | "prefix": "endjs",
316 | "body": "{% endjs %}$0",
317 | "description": "endjs",
318 | "scope": "text.html.twig"
319 | },
320 | "endmacro": {
321 | "prefix": "endmacro",
322 | "body": "{% endmacro %}$0",
323 | "description": "endmacro",
324 | "scope": "text.html.twig"
325 | },
326 | "endnav": {
327 | "prefix": "endnav",
328 | "body": "{% endnav %}$0",
329 | "description": "endnav",
330 | "scope": "text.html.twig"
331 | },
332 | "endset": {
333 | "prefix": "endset",
334 | "body": "{% endset %}$0",
335 | "description": "endset",
336 | "scope": "text.html.twig"
337 | },
338 | "endspaceless": {
339 | "prefix": "endspaceless",
340 | "body": "{% endspaceless %}$0",
341 | "description": "endspaceless",
342 | "scope": "text.html.twig"
343 | },
344 | "endswitch": {
345 | "prefix": "endswitch",
346 | "body": "{% endswitch %}$0",
347 | "description": "endswitch",
348 | "scope": "text.html.twig"
349 | },
350 | "endverbatim": {
351 | "prefix": "endverbatim",
352 | "body": "{% endverbatim %}$0",
353 | "description": "endverbatim",
354 | "scope": "text.html.twig"
355 | },
356 | "exit": {
357 | "prefix": "exit",
358 | "body": "{% exit ${1:404} %}",
359 | "description": "exit",
360 | "scope": "text.html.twig"
361 | },
362 | "extends": {
363 | "prefix": "extends",
364 | "body": "{% extends \"${1:template}\" %}$0",
365 | "description": "extends",
366 | "scope": "text.html.twig"
367 | },
368 | "filterb": {
369 | "prefix": "filterb",
370 | "body": "{% filter ${1:name} %}\n\t$0\n{% endfilter %}",
371 | "description": "filter (block)",
372 | "scope": "text.html.twig"
373 | },
374 | "filter": {
375 | "prefix": "filter",
376 | "body": "{% filter ${1:name} %}$0{% endfilter %}",
377 | "description": "filter",
378 | "scope": "text.html.twig"
379 | },
380 | "floor": {
381 | "prefix": "floor",
382 | "body": "floor($1)$0",
383 | "description": "floor",
384 | "scope": "text.html.twig"
385 | },
386 | "fore": {
387 | "prefix": "fore",
388 | "body":
389 | "{% for ${1:item} in ${2:items} %}\n\t$3\n{% else %}\n\t$0\n{% endfor %}",
390 | "description": "for ... else",
391 | "scope": "text.html.twig"
392 | },
393 | "for": {
394 | "prefix": "for",
395 | "body": "{% for ${1:item} in ${2:items} %}\n\t$0\n{% endfor %}",
396 | "description": "for",
397 | "scope": "text.html.twig"
398 | },
399 | "from": {
400 | "prefix": "from",
401 | "body": "{% from \"${1:template}\" import \"${2:macro}\" %}$0",
402 | "description": "from",
403 | "scope": "text.html.twig"
404 | },
405 | "endbody": {
406 | "prefix": "endbody",
407 | "body": "{{ endBody() }}\n$0",
408 | "description": "endBody",
409 | "scope": "text.html.twig"
410 | },
411 | "head": {
412 | "prefix": "head",
413 | "body": "{{ head() }}\n$0",
414 | "description": "head",
415 | "scope": "text.html.twig"
416 | },
417 | "if": {
418 | "prefix": "if",
419 | "body": "{% if ${1:condition} %}$2{% endif %}\n$0",
420 | "description": "if",
421 | "scope": "text.html.twig"
422 | },
423 | "ifb": {
424 | "prefix": "ifb",
425 | "body": "{% if ${1:condition} %}\n\t$0\n{% endif %}",
426 | "description": "if (block)",
427 | "scope": "text.html.twig"
428 | },
429 | "ife": {
430 | "prefix": "ife",
431 | "body": "{% if ${1:condition} %}\n\t$2\n{% else %}\n\t$0\n{% endif %}",
432 | "description": "if ... else",
433 | "scope": "text.html.twig"
434 | },
435 | "if1": {
436 | "prefix": "if",
437 | "body": "{% if ${1:condition} %}$0{% endif %}",
438 | "description": "if",
439 | "scope": "text.html.twig"
440 | },
441 | "ifchildren": {
442 | "prefix": "ifchildren",
443 | "body": "{% ifchildren %}\n\t$1\n{% endifchildren %}\n$0",
444 | "description": "ifchildren",
445 | "scope": "text.html.twig"
446 | },
447 | "import": {
448 | "prefix": "import",
449 | "body": "{% import \"${1:template}\" as ${2:name} %}$0",
450 | "description": "import",
451 | "scope": "text.html.twig"
452 | },
453 | "importself": {
454 | "prefix": "importself",
455 | "body": "{% import _self as ${1:name} %}$0",
456 | "description": "importself",
457 | "scope": "text.html.twig"
458 | },
459 | "inckv": {
460 | "prefix": "inckv",
461 | "body":
462 | "{% include \"${1:template}\" with {\n\t${2:key}: ${3:\"${4:value}\"}\n} %}\n$0",
463 | "description": "include w/ key/value",
464 | "scope": "text.html.twig"
465 | },
466 | "include": {
467 | "prefix": "include",
468 | "body": "{% include \"${1:template}\" %}$0",
469 | "description": "include",
470 | "scope": "text.html.twig"
471 | },
472 | "inc": {
473 | "prefix": "inc",
474 | "body": "{% include \"${1:template}\" %}$0",
475 | "description": "inc",
476 | "scope": "text.html.twig"
477 | },
478 | "incp": {
479 | "prefix": "incp",
480 | "body": "{% include \"${1:template}\"${2: with ${3:params} }%}$0",
481 | "description": "include w/ params",
482 | "scope": "text.html.twig"
483 | },
484 | "css1": {
485 | "prefix": "css",
486 | "body": "{% do view.registerCssFile(\"${1:/resources/css/global.css}\") %}\n$0",
487 | "description": "registerCssFile",
488 | "scope": "text.html.twig"
489 | },
490 | "js": {
491 | "prefix": "js",
492 | "body": "{% js %}\n\t$1\n{% endjs %}\n$0",
493 | "description": "js",
494 | "scope": "text.html.twig"
495 | },
496 | "js1": {
497 | "prefix": "js",
498 | "body": "{% do view.registerJsFile(\"${1:/resources/js/global.js}\") %}\n$0",
499 | "description": "registerJsFile",
500 | "scope": "text.html.twig"
501 | },
502 | "css": {
503 | "prefix": "css",
504 | "body": "{% css %}\n\t$1\n{% endcss %}\n$0",
505 | "description": "css",
506 | "scope": "text.html.twig"
507 | },
508 | "macro": {
509 | "prefix": "macro",
510 | "body": "{% macro ${1:name}(${2:params}) %}\n\t$0\n{% endmacro %}",
511 | "description": "macro",
512 | "scope": "text.html.twig"
513 | },
514 | "matrix": {
515 | "prefix": "matrix",
516 | "body":
517 | "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% if block.type == \"${2:blockHandle}\" %}\n\t\t{{ block.${3:fieldHandle} }}\n\t{% endif %}\n\n\t{% if block.type == \"${4:blockHandle}\" %}\n\t\t{{ block.${5:fieldHandle} }}\n\t{% endif %}\n\n{% endfor %}\n$0",
518 | "description": "matrix",
519 | "scope": "text.html.twig"
520 | },
521 | "matrixif": {
522 | "prefix": "matrixif",
523 | "body":
524 | "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% if block.type == \"${2:blockHandle}\" %}\n\t\t{{ block.${3:fieldHandle} }}\n\t{% endif %}\n\n\t{% if block.type == \"${4:blockHandle}\" %}\n\t\t{{ block.${5:fieldHandle} }}\n\t{% endif %}\n\n{% endfor %}\n$0",
525 | "description": "matrixif",
526 | "scope": "text.html.twig"
527 | },
528 | "matrixifelse": {
529 | "prefix": "matrixifelse",
530 | "body":
531 | "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% if block.type == \"${2:blockHandle}\" %}\n\n\t\t{{ block.${3:fieldHandle} }}\n\n\t{% elseif block.type == \"${4:blockHandle}\" %}\n\n\t\t$0\n\t\n\t{% endif %}\n\n{% endfor %}",
532 | "description": "matrixifelse",
533 | "scope": "text.html.twig"
534 | },
535 | "matrixswitch": {
536 | "prefix": "matrixswitch",
537 | "body":
538 | "{% for block in ${1:entry.matrixFieldHandle}.all() %}\n\n\t{% switch block.type %}\n\n\t\t{% case \"${2:blockHandle}\" %}\n\n\t\t\t{{ block.${3:fieldHandle} }}\n\n\t\t{% case \"${4:blockHandle}\" %}\n\n\t\t\t$0\n\n\t{% endswitch %}\n\n{% endfor %}",
539 | "description": "matrixswitch",
540 | "scope": "text.html.twig"
541 | },
542 | "max": {
543 | "prefix": "max",
544 | "body": "max(${1:$2, $3})$0",
545 | "description": "max",
546 | "scope": "text.html.twig"
547 | },
548 | "min": {
549 | "prefix": "min",
550 | "body": "min(${1:$2, $3})$0",
551 | "description": "min",
552 | "scope": "text.html.twig"
553 | },
554 | "nav": {
555 | "prefix": "nav",
556 | "body": "{% nav ${1:item} in ${2:items} %}\n\t$3\n{% endnav %}\n$0",
557 | "description": "nav",
558 | "scope": "text.html.twig"
559 | },
560 | "paginate": {
561 | "prefix": "paginate",
562 | "body":
563 | "{% paginate ${1:elements} as ${2:pageInfo}, ${3:pageEntries} %}\n\n{% for item in ${3:pageEntries} %}\n\t$0\n{% endfor %}\n\n{% if ${2:pageInfo}.prevUrl %}Previous Page{% endif %}\n{% if ${2:pageInfo}.nextUrl %}Next Page{% endif %}",
564 | "description": "paginate simple",
565 | "scope": "text.html.twig"
566 | },
567 | "paginate1": {
568 | "prefix": "paginate",
569 | "body":
570 | "{# PAGINATION\n\t\t\nFor this pagination to work properly, we need to be sure to set\nthe paginateBase variable in the template we are including the \npagination in.\n\n{% set paginateBase = \"/blog/p\" %}\n#}\n\n{% if pageInfo.totalPages > 1 %}\n