├── .eslintrc.json
├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
└── settings.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── extension
└── index.js
├── images
└── icon.png
├── package-lock.json
├── package.json
├── rollup.config.js
└── src
├── extension.js
├── hover
├── filters.json
├── functions.json
└── twig.json
├── languages
└── twig.configuration.json
├── snippets
└── snippets.json
└── syntaxes
└── twig.tmLanguage
/.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 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behavior to automatically normalize line endings.
2 | * text=auto
3 |
4 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [mblode]
4 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.enable": true
3 | }
4 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | test/**
4 | .gitignore
5 | jsconfig.json
6 | vsc-extension-quickstart.md
7 | .eslintrc.json
8 |
--------------------------------------------------------------------------------
/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 | - Create new extension based on Twig Language 1
63 |
64 | ### Changed
65 |
66 | - Change name to Twig Language 2
67 | - Update readme based on name change
68 | - Change activation events
69 |
--------------------------------------------------------------------------------
/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 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
VS Code Twig Language 2 👋
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | - Syntax highlighting
18 | - Snippets
19 | - Emmet
20 | - Pretty Diff 3 Formatting
21 | - Hover
22 |
23 | ## What has changed since version 1?
24 |
25 | This extension does **not** have HTML Intellisense. If you need HTML Intellisense (which can be quite useful), please download my other Twig Language extension: https://github.com/mblode/vscode-twig-language.
26 |
27 | I have created a new extension to fix the issues that I (and all of you) were having with file association, commenting and VS Code UI issues.
28 |
29 | Simply add these lines to your VS Code settings to get emmet working and also to associate HTML files as twig syntax.
30 |
31 | ```
32 | "files.associations": {
33 | "*.html": "twig"
34 | },
35 | "emmet.includeLanguages": {
36 | "twig": "html"
37 | },
38 | ```
39 |
40 | ## Installation
41 |
42 | Install through Visual Studio Code extensions. Search for `Twig Language 2`
43 |
44 | [Visual Studio Code Market Place: Twig Language 2](https://marketplace.visualstudio.com/items?itemName=mblode.twig-language-2)
45 |
46 | ## Configuration
47 |
48 | Restart VS Code after making changes to Twig Language 2 extension settings.
49 |
50 | ## Documentation
51 |
52 | Twig Language 2 is a Visual Studio Code extension that provides snippets, syntax highlighting, hover, and formatting for the Twig file format.
53 |
54 | ### Twig syntax highlighting and language support
55 |
56 | This extension provides language support for the Twig syntax.
57 |
58 | ### Code formatter/beautifier for Twig files
59 |
60 | Using PrettyDiff, this extension implements the only working code formatter for Twig files in VS Code.
61 |
62 | ### Information about Twig code on hover
63 |
64 | VS Code Twig language 2 shows information about the symbol/object that's below the mouse cursor when you hover within Twig files.
65 |
66 | ### Craft CMS/Twig code snippets
67 |
68 | Adds a set of Craft CMS/Twig code snippets to use in your Twig templates.
69 |
70 | ### Generic Triggers
71 |
72 | ```twig
73 |
74 | do {% do ... %}
75 | extends {% extends 'template' %}
76 | from {% from 'template' import 'macro' %}
77 | import {% import 'template' as name %}
78 | importself {% import _self as name %}
79 | inc, include {% include 'template' %}
80 | incp {% include 'template' with params %}
81 | inckv {% include 'template' with { key: value } %}
82 | use {% use 'template' %}
83 |
84 | autoescape {% autoescape 'type' %}...{% endautoescape %}
85 | block, blockb {% block name %} ... {% endblock %}
86 | blockf {{ block('...') }}
87 | embed {% embed "template" %}...{% endembed %}
88 | filter, filterb {% filter name %} ... {% endfilter %}
89 | macro {% macro name(params) %}...{% endmacro %}
90 | set, setb {% set var = value %}
91 | spaceless {% spaceless %}...{% endspaceless %}
92 | verbatim {% verbatim %}...{% endverbatim %}
93 |
94 | if, ifb {% if condition %} ... {% endif %}
95 | ife {% if condition %} ... {% else %} ... {% endif %}
96 | for {% for item in seq %} ... {% endfor %}
97 | fore {% for item in seq %} ... {% else %} ... {% endfor %}
98 |
99 | else {% else %}
100 | endif {% endif %}
101 | endfor {% endfor %}
102 | endset {% endset %}
103 | endblock {% endblock %}
104 | endfilter {% endfilter %}
105 | endautoescape {% endautoescape %}
106 | endembed {% endembed %}
107 | endfilter {% endfilter %}
108 | endmacro {% endmacro %}
109 | endspaceless {% endspaceless %}
110 | endverbatim {% endverbatim %}
111 |
112 | ```
113 |
114 | ### Craft Triggers
115 |
116 | ```twig
117 | asset craft.assets.one()
118 | assets, assetso craft.assets loop
119 | categories, categorieso craft.categories loop
120 | entries, entrieso craft.entries loop
121 | feed craft.app.feeds.getFeedItems loop
122 | t | t
123 | replace | replace('search', 'replace')
124 | replacex | replace('/(search)/i', 'replace')
125 | split | split('\n')
126 | tags, tagso craft.tags loop
127 | users, userso craft.users loop
128 |
129 | cache {% cache %}...{% endcache %}
130 | children {% children %}
131 | exit {% exit 404 %}
132 | ifchildren {% ifchildren %}...{% endifchildren %}
133 | css {% css %}...{% endcss %}
134 | registercssfile {% do view.registerCssFile("/resources/css/global.css") %}
135 | js {% js %}...{% endjs %}
136 | registerjsfile {% do view.registerJsFile("/resources/js/global.js") %}
137 | matrix, matrixif Basic Matrix field loop using if statements
138 | matrixifelse Basic Matrix field loop using if/elseif
139 | matrixswitch Basic Matrix field loop using switch
140 | nav {% nav item in items %}...{% endnav %}
141 | paginate Outputs example of pagination and prev/next links
142 | redirect {% redirect 'login' %}
143 | requirelogin {% requireLogin %}
144 | requirepermission {% requirePermission "spendTheNight" %}
145 | switch {% switch variable %}...{% endswitch %}
146 |
147 | csrf {{ csrfInput() }}
148 | endbody {{ endBody() }}
149 | head {{ head() }}
150 |
151 | getparam craft.app.request.getParam()
152 | getbodyparam craft.app.request.getBodyParam()
153 | getqueryparam craft.app.request.getQueryParam()
154 | getsegment craft.app.request.getSegment()
155 |
156 | case {% case "value" %}
157 | endcache {% endcache %}
158 | endifchildren {% endifchildren %}
159 | endcss {% endcss %}
160 | endjs {% endjs %}
161 | endnav {% endnav %}
162 |
163 | ceil ceil()
164 | floor floor()
165 | max max()
166 | min min()
167 | shuffle shuffle()
168 | random random()
169 | round num | round()
170 | url, urla url('path'), url('path', params, 'http', false)
171 |
172 | rss Example rss feed
173 |
174 | dd {{ dump() }}
{% exit %}
175 | dump {{ dump() }}
176 | ```
177 |
178 | ### Example Forms
179 |
180 | ```twig
181 |
182 | formlogin Example login form
183 | formuserprofile Example user profile form
184 | formuserregistration Example user registration form
185 | formforgotpassword Example forgot password form
186 | formsetpassword Example set password form
187 | formsearch Example search form
188 | formsearchresults Example search form results
189 |
190 | ```
191 |
192 | ### Reference Hints
193 |
194 | ```twig
195 |
196 | info All craft.assets properties and template tags
197 | info All craft.crategories properties and template tags
198 | info All craft.config properties and template tags
199 | info All craft.entries properties and template tags
200 | info All craft.feeds properties and template tags
201 | info All craft.fields properties and template tags
202 | info All craft.globals properties and template tags
203 | info All craft.request properties and template tags
204 | info All craft.sections properties and template tags
205 | info All craft.session properties and template tags
206 | info All craft.tags properties and template tags
207 | info All craft.users properties and template tags
208 | info All craft globals (site info, date, users, template tags)
209 |
210 | ```
211 |
212 | ## Author
213 |
214 | 👤 **Matthew Blode**
215 |
216 | * Github: [@mblode](https://github.com/mblode)
217 |
218 | ## 🤝 Contributing
219 |
220 | Contributions, issues and feature requests are welcome !
Feel free to check [issues page](https://github.com/mblode/vscode-twig-language-2/issues).
221 |
222 | ## Show your support
223 |
224 | Give a ⭐️ if this project helped you !
225 |
226 | ## 📝 License
227 |
228 | Copyright © 2019 [Matthew Blode](https://github.com/mblode).
229 | This project is [MIT](https://github.com/mblode/vscode-twig-language-2/blob/master/LICENSE.md) licensed.
230 |
--------------------------------------------------------------------------------
/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\tTable Of Contents
\n\t...\n\t{{ parent() }}\n{% endblock %}"};const random={prefix:"random",hover:"",body:"{% set ${result} = random($1) %}$2",description:"(function) returns a random value depending on the supplied parameter type",example:"{{ random(['apple', 'orange', 'citrus']) }}\n{# example output: orange #}\n\n{{ random('ABC') }}\n{# example output: C #}\n\n{{ random() }}\n{# example output: 15386094 (works as the native PHP mt_rand function) #}\n\n{{ random(5) }}\n{# example output: 3 #}"};const range={prefix:"range",body:"range(${low}, ${high}, ${step})",description:"(function) Returns an array of elements from low to high, inclusive",example:"{% set result = range(0, 6, 2) %}\n{% dump(result) %}\n{# output: array(0, 2, 4, 6) #}"};const source={prefix:"source",body:"{{ source('${template}.twig') }}$1",description:"(function) returns the content of a template without rendering it",example:""};const template_from_string={prefix:"template_from_string",body:"{{ include(template_from_string(\"$1\")) }}$2",description:"(function) loads a template from a string",example:"{{ include(template_from_string(\"Hello {{ name }}\")) }}"};var functionsArr = {attribute:attribute,block:block,constant:constant,cycle:cycle,date:date$1,dump:dump,include:include,max:max,min:min,parent:parent,random:random,"range set": {prefix:"range set",body:"{% set ${result} = range(${low}, ${high}, ${step}) %}$1",description:"(function) Returns an array of elements from low to high, inclusive",example:"{% set result = range(0, 6, 2) %}\n{% dump(result) %}\n{# output: array(0, 2, 4, 6) #}"},range:range,source:source,template_from_string:template_from_string};
14 |
15 | const show={prefix:"show",body:"{{ $1 }}",description:"{{ }}"};const execute={prefix:"execute",body:"{% $1 %}",description:"{% %}"};const autoescape={prefix:"autoescape",body:["{% autoescape %}","\t$1","{% endautoescape %}"],description:"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",example:"{% 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 %}"};const block$1={prefix:"block",body:["{% block ${name} %}","\t$1","{% endblock ${name} %}"],description:"When a template uses inheritance and if you want to print a block multiple times, use the block function"};const embed={prefix:"embed",body:["{% embed \"${filename}.twig\" %}","\t$1","{% endembed %}"],description:"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"};const filter={prefix:"filter",body:["{% filter ${filter name} %}","\t$1","{% endfilter %}"],description:"Filter sections allow you to apply regular Twig filters on a block of template data. Just wrap the code in the special filter section",example:"{% filter lower | escape %}\n SOME TEXT\n{% endfilter %}\n\n{# outputs \"<strong>some text</strong>\" #}"};const flush={prefix:"flush",body:["{% flush %}"],description:"The flush tag tells Twig to flush the output buffer",example:"{% flush %}"};const loop={prefix:"loop",body:"loop.",description:"special variables inside of a for loop block"};const _self={prefix:"_self",body:"_self",description:"To import macros from the current file, use the special _self variable for the source"};const include$1={prefix:"include",body:"{% include \"${filename}.twig\" %}",description:"The include statement includes a template and returns the rendered content of that file into the current namespace"};const macro={prefix:"macro",body:["{% macro ${name}($1) %}","\t$2","{% endmacro %}"],description:"Twig snippets"};const sandbox={prefix:"sandbox",body:["{% sandbox %}","\t$1","{% endsandbox %}"],description:"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"};const set={prefix:"set",body:["{% set ${name} = ${value} %}$1"],description:"Assign values to variables"};const spaceless={prefix:"spaceless",body:["{% spaceless %}","\t$1","{% endspaceless %}"],description:"Use the spaceless tag to remove whitespace between HTML tags, not whitespace within HTML tags or whitespace in plain text"};const use={prefix:"use",body:"{% use \"${filename}.twig\" %}",description:"Twig snippets"};const verbatim={prefix:"verbatim",body:["{% verbatim %}","\t$1","{% endverbatim %}"],description:"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"};var twigArr = {show:show,execute:execute,autoescape:autoescape,block:block$1,"do": {prefix:"do",body:["{% do $1 %}"],description:"The do tag works exactly like the regular variable expression ({{ ... }}) just that it doesn't print anything",example:"{% do 1 + 2 %}"},embed:embed,"extends": {prefix:"extends",body:"{% extends \"${filename}.twig\" %}",description:"Twig snippets"},filter:filter,flush:flush,"for": {prefix:"for",body:["{% for ${row} in ${array} %}","\t$1","{% endfor %}"],description:"Loop over each item in a sequence"},"for if": {prefix:"for if",body:["{% for ${row} in ${array} if ${condition} %}","\t$1","{% endfor %}"],description:"Loop over each item in a sequence"},"for else": {prefix:"for else",body:["{% for ${row} in ${array} %}","\t$1","{% else %}","\t$2","{% endfor %}"],description:"Loop over each item in a sequence"},"for if else": {prefix:"for if else",body:["{% for ${row} in ${array} if ${condition} %}","\t$1","{% else %}","\t$2","{% endfor %}"],description:"Loop over each item in a sequence"},loop:loop,"if": {prefix:"if",body:["{% if ${condition} %}","\t$1","{% endif %}"],description:"The if statement in Twig is comparable with the if statements of PHP"},"if else": {prefix:"if else",body:["{% if ${condition} %}","\t$1","{% else %}","\t$2","{% endif %}"],description:"The if statement in Twig is comparable with the if statements of PHP"},"else": {prefix:"else",body:"{% else %}",description:"The if statement in Twig is comparable with the if statements of PHP"},"else if": {prefix:"else if",body:"{% elseif ${condition} %}",description:"The if statement in Twig is comparable with the if statements of PHP"},"import": {prefix:"import",body:"{% import \"${filename}.twig\" as ${alias}%}",description:"Twig supports putting often used code into macros. These macros can go into different templates and get imported from there."},_self:_self,include:include$1,macro:macro,sandbox:sandbox,set:set,"set block": {prefix:"set (block)",body:["{% set ${name} %}","\t$1","{% endset %}"],description:"Inside code blocks you can also assign values to variables. Assignments use the set tag and can have multiple targets"},spaceless:spaceless,use:use,verbatim:verbatim};
16 |
17 | const editor = vscode__default['default'].workspace.getConfiguration('editor');
18 | const config = vscode__default['default'].workspace.getConfiguration('twig-language-2');
19 |
20 | function createHover(snippet, type) {
21 | const example = typeof snippet.example == 'undefined' ? '' : snippet.example;
22 | const description = typeof snippet.description == 'undefined' ? '' : snippet.description;
23 | return new vscode__default['default'].Hover({
24 | language: type,
25 | value: description + '\n\n' + example
26 | });
27 | }
28 |
29 | function prettyDiff(document, range) {
30 | const result = [];
31 | let output = "";
32 | let options = prettydiff__default['default'].options;
33 |
34 | let tabSize = editor.tabSize;
35 | let indentChar = " ";
36 |
37 | if (config.tabSize > 0) {
38 | tabSize = config.tabSize;
39 | }
40 |
41 | if (config.indentStyle == "tab") {
42 | tabSize = 0;
43 | indentChar = "\t";
44 | }
45 |
46 | options.source = document.getText(range);
47 | options.mode = 'beautify';
48 | options.language = 'html';
49 | options.lexer = 'markup';
50 | options.brace_line = config.braceLine;
51 | options.brace_padding = config.bracePadding;
52 | options.brace_style = config.braceStyle;
53 | options.braces = config.braces;
54 | options.comment_line = config.commentLine;
55 | options.comments = config.comments;
56 | options.compressed_css = config.compressedCss;
57 | options.correct = config.correct;
58 | options.cssInsertLines = config.cssInsertLines;
59 | options.else_line = config.elseLine;
60 | options.end_comma = config.endComma;
61 | options.force_attribute = config.forceAttribute;
62 | options.force_indent = config.forceIndent;
63 | options.format_array = config.formatArray;
64 | options.format_object = config.formatObject;
65 | options.function_name = config.functionName;
66 | options.indent_level = config.indentLevel;
67 | options.indent_char = indentChar;
68 | options.indent_size = tabSize;
69 | options.method_chain = config.methodChain;
70 | options.never_flatten = config.neverFlatten;
71 | options.new_line = config.newLine;
72 | options.no_case_indent = config.noCaseIndent;
73 | options.no_lead_zero = config.noLeadZero;
74 | options.object_sort = config.objectSort;
75 | options.preserve = config.preserve;
76 | options.preserve_comment = config.preserveComment;
77 | options.quote_convert = config.quoteConvert;
78 | options.space = config.space;
79 | options.space_close = config.spaceSlose;
80 | options.tag_merge = config.tagMerge;
81 | options.tag_sort = config.tagSort;
82 | options.ternary_line = config.ternaryLine;
83 | options.unformatted = config.unformatted;
84 | options.variable_list = config.variableList;
85 | options.vertical = config.vertical;
86 | options.wrap = config.wrap;
87 |
88 | output = prettydiff__default['default']();
89 |
90 | options.end = 0;
91 | options.start = 0;
92 |
93 | result.push(vscode__default['default'].TextEdit.replace(range, output));
94 | return result;
95 | }
96 | function activate(context) {
97 | const active = vscode__default['default'].window.activeTextEditor;
98 | if (!active || !active.document) return
99 |
100 | registerDocType('twig');
101 |
102 | function registerDocType(type) {
103 | if (config.hover === true) {
104 | context.subscriptions.push(vscode__default['default'].languages.registerHoverProvider(type, {
105 | provideHover(document, position) {
106 | const range = document.getWordRangeAtPosition(position);
107 | const word = document.getText(range);
108 |
109 | for (const snippet in snippetsArr) {
110 | if (snippetsArr[snippet].prefix == word || snippetsArr[snippet].hover == word) {
111 | return createHover(snippetsArr[snippet], type)
112 | }
113 | }
114 |
115 | for (const snippet in functionsArr) {
116 | if (functionsArr[snippet].prefix == word || functionsArr[snippet].hover == word) {
117 | return createHover(functionsArr[snippet], type)
118 | }
119 | }
120 |
121 | for (const snippet in twigArr) {
122 | if (twigArr[snippet].prefix == word || twigArr[snippet].hover == word) {
123 | return createHover(twigArr[snippet], type)
124 | }
125 | }
126 | }
127 | }));
128 | }
129 |
130 | if (config.formatting === true) {
131 | context.subscriptions.push(vscode__default['default'].languages.registerDocumentFormattingEditProvider(type, {
132 | provideDocumentFormattingEdits: function (document) {
133 | const start = new vscode__default['default'].Position(0, 0);
134 |
135 | const end = new vscode__default['default'].Position(document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length);
136 |
137 | const rng = new vscode__default['default'].Range(start, end);
138 | return prettyDiff(document, rng);
139 | }
140 | }));
141 |
142 | context.subscriptions.push(vscode__default['default'].languages.registerDocumentRangeFormattingEditProvider(type, {
143 | provideDocumentRangeFormattingEdits: function (document, range) {
144 | let end = range.end;
145 |
146 | if (end.character === 0) {
147 | end = end.translate(-1, Number.MAX_VALUE);
148 | } else {
149 | end = end.translate(0, Number.MAX_VALUE);
150 | }
151 |
152 | const rng = new vscode__default['default'].Range(new vscode__default['default'].Position(range.start.line, 0), end);
153 | return prettyDiff(document, rng);
154 | }
155 | }));
156 | }
157 | }
158 | }
159 |
160 | exports.activate = activate;
161 |
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mblode/vscode-twig-language-2/f62292b533e7c3628c3039214edf45869f8d16c9/images/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "twig-language-2",
3 | "displayName": "Twig Language 2",
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-2",
14 | "bugs": {
15 | "url": "https://github.com/mblode/vscode-twig-language-2/issues"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/mblode/vscode-twig-language-2.git"
20 | },
21 | "icon": "images/icon.png",
22 | "engines": {
23 | "vscode": "^1.30.0"
24 | },
25 | "categories": [
26 | "Formatters",
27 | "Programming Languages",
28 | "Snippets",
29 | "Other"
30 | ],
31 | "keywords": [
32 | "php",
33 | "twig",
34 | "snippets",
35 | "craft",
36 | "beautify"
37 | ],
38 | "activationEvents": [
39 | "onLanguage:twig"
40 | ],
41 | "main": "./extension/index",
42 | "contributes": {
43 | "languages": [
44 | {
45 | "id": "twig",
46 | "aliases": [
47 | "HTML (Twig)",
48 | "twig"
49 | ],
50 | "extensions": [
51 | ".twig",
52 | ".html.twig"
53 | ],
54 | "configuration": "./src/languages/twig.configuration.json"
55 | }
56 | ],
57 | "grammars": [
58 | {
59 | "language": "twig",
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": "twig",
74 | "path": "./src/snippets/snippets.json"
75 | }
76 | ],
77 | "configuration": {
78 | "type": "object",
79 | "title": "Twig Language 2",
80 | "properties": {
81 | "twig-language-2.hover": {
82 | "type": "boolean",
83 | "default": true,
84 | "description": "Whether to enable/disable Twig hover."
85 | },
86 | "twig-language-2.formatting": {
87 | "type": "boolean",
88 | "default": true,
89 | "description": "Whether to enable/disable Twig PrettyDiff formatting."
90 | },
91 | "twig-language-2.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-2.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-2.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-2.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-2.commentLine": {
118 | "type": "boolean",
119 | "default": false,
120 | "description": "If a blank new line should be forced above comments."
121 | },
122 | "twig-language-2.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-2.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-2.correct": {
133 | "type": "boolean",
134 | "default": false,
135 | "description": "Automatically correct some sloppiness in code."
136 | },
137 | "twig-language-2.cssInsertLines": {
138 | "type": "boolean",
139 | "default": false,
140 | "description": "Inserts new line characters between every CSS code block."
141 | },
142 | "twig-language-2.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-2.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-2.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-2.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-2.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-2.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-2.functionName": {
188 | "type": "boolean",
189 | "default": false,
190 | "description": "If a space should follow a JavaScript function name."
191 | },
192 | "twig-language-2.indentStyle": {
193 | "type": "string",
194 | "enum": [
195 | "space",
196 | "tab"
197 | ],
198 | "default": "tab",
199 | "description": "Choose to indent using tabs or spaces. This formatter will not use the \"Editor: Insert Spaces\" setting, nor will it use the `indent_style` setting declared in `.editorconfig` files."
200 | },
201 | "twig-language-2.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-2.tabSize": {
207 | "type": "integer",
208 | "default": 0,
209 | "description": "0 will default to the editor's tab size (`editor.tabSize`). This formatter will not use the `indent_size` setting declared in `.editorconfig` files."
210 | },
211 | "twig-language-2.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-2.neverFlatten": {
217 | "type": "boolean",
218 | "default": false,
219 | "description": "If destructured lists in script should never be flattend."
220 | },
221 | "twig-language-2.newLine": {
222 | "type": "boolean",
223 | "default": true,
224 | "description": "Insert an empty line at the end of output."
225 | },
226 | "twig-language-2.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-2.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-2.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-2.preserve": {
242 | "type": "integer",
243 | "default": 2,
244 | "description": "The maximum number of consecutive empty lines to retain."
245 | },
246 | "twig-language-2.preserveComment": {
247 | "type": "boolean",
248 | "default": false,
249 | "description": "Prevent comment reformatting due to option wrap."
250 | },
251 | "twig-language-2.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-2.space": {
262 | "type": "boolean",
263 | "default": true,
264 | "description": "Inserts a space following the function keyword for anonymous functions."
265 | },
266 | "twig-language-2.spaceClose": {
267 | "type": "boolean",
268 | "default": false,
269 | "description": "Markup self-closing tags end will end with ' />' instead of '/>'."
270 | },
271 | "twig-language-2.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-2.tagSort": {
277 | "type": "boolean",
278 | "default": false,
279 | "description": "Sort child items of each respective markup parent element."
280 | },
281 | "twig-language-2.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-2.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-2.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-2.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-2.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/extension.js:
--------------------------------------------------------------------------------
1 | import vscode from 'vscode'
2 | import prettydiff from 'prettydiff'
3 | import snippetsArr from './hover/filters.json'
4 | import functionsArr from './hover/functions.json'
5 | import twigArr from './hover/twig.json'
6 |
7 | const editor = vscode.workspace.getConfiguration('editor');
8 | const config = vscode.workspace.getConfiguration('twig-language-2');
9 |
10 | function createHover(snippet, type) {
11 | const example = typeof snippet.example == 'undefined' ? '' : snippet.example
12 | const description = typeof snippet.description == 'undefined' ? '' : snippet.description
13 | return new vscode.Hover({
14 | language: type,
15 | value: description + '\n\n' + example
16 | });
17 | }
18 |
19 | function prettyDiff(document, range) {
20 | const result = [];
21 | let output = "";
22 | let options = prettydiff.options;
23 |
24 | let tabSize = editor.tabSize;
25 | let indentChar = " ";
26 |
27 | if (config.tabSize > 0) {
28 | tabSize = config.tabSize;
29 | }
30 |
31 | if (config.indentStyle == "tab") {
32 | tabSize = 0;
33 | indentChar = "\t";
34 | }
35 |
36 | options.source = document.getText(range);
37 | options.mode = 'beautify';
38 | options.language = 'html';
39 | options.lexer = 'markup';
40 | options.brace_line = config.braceLine;
41 | options.brace_padding = config.bracePadding;
42 | options.brace_style = config.braceStyle;
43 | options.braces = config.braces;
44 | options.comment_line = config.commentLine;
45 | options.comments = config.comments;
46 | options.compressed_css = config.compressedCss;
47 | options.correct = config.correct;
48 | options.cssInsertLines = config.cssInsertLines;
49 | options.else_line = config.elseLine;
50 | options.end_comma = config.endComma;
51 | options.force_attribute = config.forceAttribute;
52 | options.force_indent = config.forceIndent;
53 | options.format_array = config.formatArray;
54 | options.format_object = config.formatObject;
55 | options.function_name = config.functionName;
56 | options.indent_level = config.indentLevel;
57 | options.indent_char = indentChar;
58 | options.indent_size = tabSize;
59 | options.method_chain = config.methodChain;
60 | options.never_flatten = config.neverFlatten;
61 | options.new_line = config.newLine;
62 | options.no_case_indent = config.noCaseIndent;
63 | options.no_lead_zero = config.noLeadZero;
64 | options.object_sort = config.objectSort;
65 | options.preserve = config.preserve;
66 | options.preserve_comment = config.preserveComment;
67 | options.quote_convert = config.quoteConvert;
68 | options.space = config.space;
69 | options.space_close = config.spaceSlose;
70 | options.tag_merge = config.tagMerge;
71 | options.tag_sort = config.tagSort;
72 | options.ternary_line = config.ternaryLine;
73 | options.unformatted = config.unformatted;
74 | options.variable_list = config.variableList;
75 | options.vertical = config.vertical;
76 | options.wrap = config.wrap;
77 |
78 | output = prettydiff();
79 |
80 | options.end = 0;
81 | options.start = 0;
82 |
83 | result.push(vscode.TextEdit.replace(range, output));
84 | return result;
85 | };
86 |
87 | function activate(context) {
88 | const active = vscode.window.activeTextEditor
89 | if (!active || !active.document) return
90 |
91 | registerDocType('twig');
92 |
93 | function registerDocType(type) {
94 | if (config.hover === true) {
95 | context.subscriptions.push(vscode.languages.registerHoverProvider(type, {
96 | provideHover(document, position) {
97 | const range = document.getWordRangeAtPosition(position);
98 | const word = document.getText(range);
99 |
100 | for (const snippet in snippetsArr) {
101 | if (snippetsArr[snippet].prefix == word || snippetsArr[snippet].hover == word) {
102 | return createHover(snippetsArr[snippet], type)
103 | }
104 | }
105 |
106 | for (const snippet in functionsArr) {
107 | if (functionsArr[snippet].prefix == word || functionsArr[snippet].hover == word) {
108 | return createHover(functionsArr[snippet], type)
109 | }
110 | }
111 |
112 | for (const snippet in twigArr) {
113 | if (twigArr[snippet].prefix == word || twigArr[snippet].hover == word) {
114 | return createHover(twigArr[snippet], type)
115 | }
116 | }
117 | }
118 | }));
119 | }
120 |
121 | if (config.formatting === true) {
122 | context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider(type, {
123 | provideDocumentFormattingEdits: function (document) {
124 | const start = new vscode.Position(0, 0)
125 |
126 | const end = new vscode.Position(document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length);
127 |
128 | const rng = new vscode.Range(start, end)
129 | return prettyDiff(document, rng);
130 | }
131 | }));
132 |
133 | context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider(type, {
134 | provideDocumentRangeFormattingEdits: function (document, range) {
135 | let end = range.end
136 |
137 | if (end.character === 0) {
138 | end = end.translate(-1, Number.MAX_VALUE);
139 | } else {
140 | end = end.translate(0, Number.MAX_VALUE);
141 | }
142 |
143 | const rng = new vscode.Range(new vscode.Position(range.start.line, 0), end)
144 | return prettyDiff(document, rng);
145 | }
146 | }));
147 | }
148 | }
149 | }
150 |
151 | exports.activate = activate;
152 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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\tTable Of Contents
\n\t...\n\t{{ parent() }}\n{% endblock %}"
73 | },
74 | "random": {
75 | "prefix": "random",
76 | "hover": "",
77 | "body": "{% set ${result} = random($1) %}$2",
78 | "description":
79 | "(function) returns a random value depending on the supplied parameter type",
80 | "example":
81 | "{{ random(['apple', 'orange', 'citrus']) }}\n{# example output: orange #}\n\n{{ random('ABC') }}\n{# example output: C #}\n\n{{ random() }}\n{# example output: 15386094 (works as the native PHP mt_rand function) #}\n\n{{ random(5) }}\n{# example output: 3 #}"
82 | },
83 | "range set": {
84 | "prefix": "range set",
85 | "body": "{% set ${result} = range(${low}, ${high}, ${step}) %}$1",
86 | "description":
87 | "(function) Returns an array of elements from low to high, inclusive",
88 | "example":
89 | "{% set result = range(0, 6, 2) %}\n{% dump(result) %}\n{# output: array(0, 2, 4, 6) #}"
90 | },
91 | "range": {
92 | "prefix": "range",
93 | "body": "range(${low}, ${high}, ${step})",
94 | "description":
95 | "(function) Returns an array of elements from low to high, inclusive",
96 | "example":
97 | "{% set result = range(0, 6, 2) %}\n{% dump(result) %}\n{# output: array(0, 2, 4, 6) #}"
98 | },
99 | "source": {
100 | "prefix": "source",
101 | "body": "{{ source('${template}.twig') }}$1",
102 | "description":
103 | "(function) returns the content of a template without rendering it",
104 | "example": ""
105 | },
106 | "template_from_string": {
107 | "prefix": "template_from_string",
108 | "body": "{{ include(template_from_string(\"$1\")) }}$2",
109 | "description": "(function) loads a template from a string",
110 | "example": "{{ include(template_from_string(\"Hello {{ name }}\")) }}"
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/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/languages/twig.configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "blockComment": [ "{#", "#}" ]
4 | },
5 | "brackets": [
6 | ["{", "}"],
7 | ["[", "]"],
8 | ["(", ")"]
9 | ],
10 | "surroundingPairs": [
11 | { "open": "'", "close": "'" },
12 | { "open": "\"", "close": "\"" },
13 | { "open": "{", "close": "}"},
14 | { "open": "[", "close": "]"},
15 | { "open": "(", "close": ")" },
16 | { "open": "<", "close": ">" }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/src/snippets/snippets.json:
--------------------------------------------------------------------------------
1 | {
2 | "apply": {
3 | "prefix": "apply",
4 | "body": "{% apply %}\n\t$0\n{% endapply %}",
5 | "description": "apply",
6 | "scope": "text.html.twig"
7 | },
8 | "asset": {
9 | "prefix": "asset",
10 | "body":
11 | "{% set asset = ${1:entry.assetFieldHandle}.one() %}\n\n{% if asset %}\n\t
\n{% endif %}",
12 | "description": "asset",
13 | "scope": "text.html.twig"
14 | },
15 | "assets": {
16 | "prefix": "assets",
17 | "body":
18 | "{% for image in craft.assets.\n\t.sourceId(\"${1:1}\")\n\t.kind(\"${2:image}\")\n\t.limit(${3:10})\n}).all() %}\n\t
\n{% endfor %}\n$0",
19 | "description": "craft.assets",
20 | "scope": "text.html.twig"
21 | },
22 | "autoescape": {
23 | "prefix": "autoescape",
24 | "body": "{% autoescape \"${1:type}\" %}\n\t$0\n{% endautoescape %}",
25 | "description": "autoescape",
26 | "scope": "text.html.twig"
27 | },
28 | "blockb": {
29 | "prefix": "blockb",
30 | "body": "{% block ${1:name} %}\n\t$0\n{% endblock %}",
31 | "description": "block (block)",
32 | "scope": "text.html.twig"
33 | },
34 | "block": {
35 | "prefix": "block",
36 | "body": "{% block ${1:name} %}$0{% endblock %}",
37 | "description": "block",
38 | "scope": "text.html.twig"
39 | },
40 | "blockf": {
41 | "prefix": "blockf",
42 | "body": "{{ block(\"${1:name}\") }}$0",
43 | "description": "blockf",
44 | "scope": "text.html.twig"
45 | },
46 | "cache": {
47 | "prefix": "cache",
48 | "body": "{% cache %}\n\t$1\n{% endcache %}\n$0",
49 | "description": "cache",
50 | "scope": "text.html.twig"
51 | },
52 | "case": {
53 | "prefix": "case",
54 | "body": "{% case \"${1:value}\" %}\n\t$0",
55 | "description": "case",
56 | "scope": "text.html.twig"
57 | },
58 | "children": {
59 | "prefix": "children",
60 | "body": "{% children %}$0",
61 | "description": "children",
62 | "scope": "text.html.twig"
63 | },
64 | "ceil": {
65 | "prefix": "ceil",
66 | "body": "ceil($1)$0",
67 | "description": "ceil",
68 | "scope": "text.html.twig"
69 | },
70 | "formlogin": {
71 | "prefix": "formlogin",
72 | "body":
73 | "\n\nForgot your password?
",
74 | "description": "craft.user - example login form",
75 | "scope": "text.html.twig"
76 | },
77 | "formuserprofile": {
78 | "prefix": "formuserprofile",
79 | "body":
80 | "",
81 | "description": "craft.user - example user profile form",
82 | "scope": "text.html.twig"
83 | },
84 |
85 | "formuserregistration": {
86 | "prefix": "formuserregistration",
87 | "body":
88 | "",
89 | "description": "craft.user - example user registration form",
90 | "scope": "text.html.twig"
91 | },
92 | "formforgotpassword": {
93 | "prefix": "formforgotpassword",
94 | "body":
95 | "",
96 | "description": "craft.user - example forgot password form",
97 | "scope": "text.html.twig"
98 | },
99 | "formsetpassword": {
100 | "prefix": "formsetpassword",
101 | "body":
102 | "",
103 | "description": "craft.user - example set password form",
104 | "scope": "text.html.twig"
105 | },
106 | "formsearch": {
107 | "prefix": "formsearch",
108 | "body":
109 | "",
110 | "description": "craft.entries - example search form",
111 | "scope": "text.html.twig"
112 | },
113 | "formsearchresults": {
114 | "prefix": "formsearchresults",
115 | "body":
116 | "Search Results
\n\n{% set query = craft.app.request.getParam(\"q\") %}\n{% set entries = craft.entries.search(query).orderBy(\"score\").all() %}\n\n{% if entries | length %}\n\t{{ entries | length }} results:
\n\n\t\n{% else %}\n\tYour search for “{{ query }}” didn’t return any results.
\n{% endif %}",
117 | "description": "craft.entries - example search results",
118 | "scope": "text.html.twig"
119 | },
120 | "rss": {
121 | "prefix": "rss",
122 | "body":
123 | "\n\n\t\n\t\t{{ siteName }}\n\t\t{{ siteUrl }}\n\t\t\n\t\t{{ globals.siteDescription }}\n\t\ten-us\n\t\t{{ now | rss }}\n\t\t{{ now | rss }}\n\n\t\t{% for entry in craft.entries.all() %}\n\t\t\t- \n\t\t\t\t{{ entry.title }}\n\t\t\t\t{{ entry.url }}\n\t\t\t\t{{ entry.postDate | rss }}\n\t\t\t\t{{ entry.author }}\n\t\t\t\t{{ entry.url }}\n\t\t\t\t\n\t\t\t
\n\t\t{% endfor %}\n\t\n",
124 | "description": "craft.entries - example rss feed",
125 | "scope": "text.html.twig"
126 | },
127 | "assetso": {
128 | "prefix": "assetso",
129 | "body":
130 | "{% set assets = craft.assets({\n\tsourceId: \"${1:1}\",\n\tkind: \"${2:image}\",\n\tlimit: ${3:10}\n}).all() %}\n\n{% for image in assets %}\n\t
\n{% endfor %}\n$0",
131 | "description": "craft.assets - object syntax",
132 | "scope": "text.html.twig"
133 | },
134 | "categorieso": {
135 | "prefix": "categorieso",
136 | "body":
137 | "{% set categories = craft.categories({\n\tgroup: \"${1:categoryGroupHandle}\",\n\tlimit: \"${2:11}\"\n}).all() %}\n\n\n\t{% nav category in categories %}\n\t\t- \n\t\t\t{{ category.title }}\n\t\t\t{% ifchildren %}\n\t\t\t\t
\n\t\t\t\t\t{% children %}\n\t\t\t\t
\n\t\t\t{% endifchildren %}\n\t\t \n\t{% endnav %}\n
",
138 | "description": "craft.categories - object syntax",
139 | "scope": "text.html.twig"
140 | },
141 | "categories": {
142 | "prefix": "categories",
143 | "body":
144 | "\n\t{% nav category in craft.categories\n\t\t.group(\"${1:categoryGroupHandle}\")\n\t\t.limit(${2:11})\n\t\t.all()\n\t%}\n\t\t- \n\t\t\t{{ category.title }}\n\t\t\t{% ifchildren %}\n\t\t\t\t
\n\t\t\t\t\t{% children %}\n\t\t\t\t
\n\t\t\t{% endifchildren %}\n\t\t \n\t{% endnav %}\n
",
145 | "description": "craft.categories",
146 | "scope": "text.html.twig"
147 | },
148 | "entrieso": {
149 | "prefix": "entrieso",
150 | "body":
151 | "{% set entries = craft.entries({\n\tsection: \"${1:sectionName}\",\n\tlimit: \"${2:10}\"\n}).all() %}\n\n{% for entry in entries %}\n\t{{ entry.title }}\n{% endfor %}\n$0",
152 | "description": "craft.entries - object syntax",
153 | "scope": "text.html.twig"
154 | },
155 | "entries": {
156 | "prefix": "entries",
157 | "body":
158 | "{% for entry in craft.entries\n\t.section(\"${1:sectionName}\")\n\t.limit(${2:10})\n\t.all()\n%}\n\t{{ entry.title }}\n{% endfor %}\n$0",
159 | "description": "craft.entries",
160 | "scope": "text.html.twig"
161 | },
162 | "feed": {
163 | "prefix": "feed",
164 | "body":
165 | "{% set feedUrl = \"${1:http://feeds.feedburner.com/blogandtonic}\" %}\n{% set limit = ${2:10} %}\n{% set items = craft.feeds.getFeedItems(feedUrl, limit).all() %}\n\n{% for item in items %}\n\t\n\t\t\n\t\t{{ item.authors[0].name }}
\n\t\t{{ item.date }}
\n\n\t\t{{ item.summary }}\n\t\n{% endfor %}",
166 | "description": "feed",
167 | "scope": "text.html.twig"
168 | },
169 | "t": {
170 | "prefix": "t",
171 | "body": "{{ $1 | t }}$0",
172 | "description": "translate with | t"
173 | },
174 | "replace": {
175 | "prefix": "replace",
176 | "body": "{{ ${1:$TM_SELECTED_TEXT} | replace(\"search\", \"replace\") }}$0",
177 | "description": "replace with | replace(\"search\", \"replace\")"
178 | },
179 | "replacex": {
180 | "prefix": "replacex",
181 | "body":
182 | "{{ ${1:$TM_SELECTED_TEXT} | replace(\"/(search)/i\", \"replace\") }}$0",
183 | "description": "replace regex with | replace(\"/(search)/i\", \"replace\")"
184 | },
185 | "split": {
186 | "prefix": "split",
187 | "body": "{{ ${1:$TM_SELECTED_TEXT} | split(\"\\n\") }}$0",
188 | "description": "split on | split (\"\\n\")"
189 | },
190 | "tagso": {
191 | "prefix": "tagso",
192 | "body":
193 | "{% set tags = craft.tags({\n\tgroup: \"${1:tagGroupHandle}\"\n}).all() %}\n\n\n\t{% for tag in tags %}\n\t\t- {{ tag }}
\n\t{% endfor %}\n
\n$0",
194 | "description": "craft.tags - object syntax",
195 | "scope": "text.html.twig"
196 | },
197 | "tags": {
198 | "prefix": "tags",
199 | "body":
200 | "\n\t{% for tag in craft.tags.group(\"${1:tagGroupHandle}\").all() %}\n\t\t- {{ tag }}
\n\t{% endfor %}\n
\n$0",
201 | "description": "craft.tags",
202 | "scope": "text.html.twig"
203 | },
204 | "userso": {
205 | "prefix": "userso",
206 | "body":
207 | "{% set users = craft.users({\n\tgroup: \"${1:userGroupHandle}\"\n}).all() %}\n\n{% for user in users %}\n\t{{ user.firstName }} {{ user.lastName }}\n{% endfor %}\n$0",
208 | "description": "craft.users - object syntax",
209 | "scope": "text.html.twig"
210 | },
211 | "users": {
212 | "prefix": "users",
213 | "body":
214 | "{% for user in craft.users.group(\"${1:userGroupHandle}\").all() %}\n\t{{ user.firstName }} {{ user.lastName }}\n{% endfor %}\n$0",
215 | "description": "craft.users",
216 | "scope": "text.html.twig"
217 | },
218 | "csrf": {
219 | "prefix": "csrf",
220 | "body": "{{ csrfInput() }}\n$0",
221 | "description": "csrf",
222 | "scope": "text.html.twig"
223 | },
224 | "dd": {
225 | "prefix": "dd",
226 | "body": "\n\t{{ dump($1) }}\n
\n{% exit %}$0",
227 | "description": "dump and die",
228 | "scope": "text.html.twig"
229 | },
230 | "do": {
231 | "prefix": "do",
232 | "body": "{% do $1 %}$0",
233 | "description": "do",
234 | "scope": "text.html.twig"
235 | },
236 | "dojs": {
237 | "prefix": "dojs",
238 | "body": "{% do view.registerJsFile \"${1:url}\" %}$0",
239 | "description": "do js",
240 | "scope": "text.html.twig"
241 | },
242 | "docss": {
243 | "prefix": "docss",
244 | "body": "{% do view.registerCssFile \"${1:url}\" %}$0",
245 | "description": "do css",
246 | "scope": "text.html.twig"
247 | },
248 | "dump": {
249 | "prefix": "dump",
250 | "body": "\n\t{{ dump($1) }}\n
",
251 | "description": "dump",
252 | "scope": "text.html.twig"
253 | },
254 | "else": {
255 | "prefix": "else",
256 | "body": "{% else %}\n\t$0",
257 | "description": "else",
258 | "scope": "text.html.twig"
259 | },
260 | "elseif": {
261 | "prefix": "elseif",
262 | "body": "{% elseif %}\n\t$0",
263 | "description": "elseif",
264 | "scope": "text.html.twig"
265 | },
266 | "embed": {
267 | "prefix": "embed",
268 | "body": "{% embed \"${1:template}\" %}\n\t$0\n{% endembed %}",
269 | "description": "embed",
270 | "scope": "text.html.twig"
271 | },
272 | "endapply": {
273 | "prefix": "endapply",
274 | "body": "{% endapply %}$0",
275 | "description": "endapply",
276 | "scope": "text.html.twig"
277 | },
278 | "endautoescape": {
279 | "prefix": "endautoescape",
280 | "body": "{% endautoescape %}$0",
281 | "description": "endautoescape",
282 | "scope": "text.html.twig"
283 | },
284 | "endblock": {
285 | "prefix": "endblock",
286 | "body": "{% endblock %}$0",
287 | "description": "endblock",
288 | "scope": "text.html.twig"
289 | },
290 | "endcache": {
291 | "prefix": "endcache",
292 | "body": "{% endcache %}$0",
293 | "description": "endcache",
294 | "scope": "text.html.twig"
295 | },
296 | "endembed": {
297 | "prefix": "endembed",
298 | "body": "{% endembed %}$0",
299 | "description": "endembed",
300 | "scope": "text.html.twig"
301 | },
302 | "endfilter": {
303 | "prefix": "endfilter",
304 | "body": "{% endfilter %}$0",
305 | "description": "endfilter",
306 | "scope": "text.html.twig"
307 | },
308 | "endfor": {
309 | "prefix": "endfor",
310 | "body": "{% endfor %}$0",
311 | "description": "endfor",
312 | "scope": "text.html.twig"
313 | },
314 | "endif": {
315 | "prefix": "endif",
316 | "body": "{% endif %}$0",
317 | "description": "endif",
318 | "scope": "text.html.twig"
319 | },
320 | "endifchildren": {
321 | "prefix": "endifchildren",
322 | "body": "{% endifchildren %}$0",
323 | "description": "endifchildren",
324 | "scope": "text.html.twig"
325 | },
326 | "endcss": {
327 | "prefix": "endcss",
328 | "body": "{% endcss %}$0",
329 | "description": "endcss",
330 | "scope": "text.html.twig"
331 | },
332 | "endjs": {
333 | "prefix": "endjs",
334 | "body": "{% endjs %}$0",
335 | "description": "endjs",
336 | "scope": "text.html.twig"
337 | },
338 | "endmacro": {
339 | "prefix": "endmacro",
340 | "body": "{% endmacro %}$0",
341 | "description": "endmacro",
342 | "scope": "text.html.twig"
343 | },
344 | "endnav": {
345 | "prefix": "endnav",
346 | "body": "{% endnav %}$0",
347 | "description": "endnav",
348 | "scope": "text.html.twig"
349 | },
350 | "endset": {
351 | "prefix": "endset",
352 | "body": "{% endset %}$0",
353 | "description": "endset",
354 | "scope": "text.html.twig"
355 | },
356 | "endspaceless": {
357 | "prefix": "endspaceless",
358 | "body": "{% endspaceless %}$0",
359 | "description": "endspaceless",
360 | "scope": "text.html.twig"
361 | },
362 | "endswitch": {
363 | "prefix": "endswitch",
364 | "body": "{% endswitch %}$0",
365 | "description": "endswitch",
366 | "scope": "text.html.twig"
367 | },
368 | "endtrans": {
369 | "prefix": "endtrans",
370 | "body": "{% endtrans %}$0",
371 | "description": "endtrans",
372 | "scope": "text.html.twig"
373 | },
374 | "endverbatim": {
375 | "prefix": "endverbatim",
376 | "body": "{% endverbatim %}$0",
377 | "description": "endverbatim",
378 | "scope": "text.html.twig"
379 | },
380 | "exit": {
381 | "prefix": "exit",
382 | "body": "{% exit ${1:404} %}",
383 | "description": "exit",
384 | "scope": "text.html.twig"
385 | },
386 | "extends": {
387 | "prefix": "extends",
388 | "body": "{% extends \"${1:template}\" %}$0",
389 | "description": "extends",
390 | "scope": "text.html.twig"
391 | },
392 | "filterb": {
393 | "prefix": "filterb",
394 | "body": "{% filter ${1:name} %}\n\t$0\n{% endfilter %}",
395 | "description": "filter (block)",
396 | "scope": "text.html.twig"
397 | },
398 | "filter": {
399 | "prefix": "filter",
400 | "body": "{% filter ${1:name} %}$0{% endfilter %}",
401 | "description": "filter",
402 | "scope": "text.html.twig"
403 | },
404 | "floor": {
405 | "prefix": "floor",
406 | "body": "floor($1)$0",
407 | "description": "floor",
408 | "scope": "text.html.twig"
409 | },
410 | "fore": {
411 | "prefix": "fore",
412 | "body":
413 | "{% for ${1:item} in ${2:items} %}\n\t$3\n{% else %}\n\t$0\n{% endfor %}",
414 | "description": "for ... else",
415 | "scope": "text.html.twig"
416 | },
417 | "for": {
418 | "prefix": "for",
419 | "body": "{% for ${1:item} in ${2:items} %}\n\t$0\n{% endfor %}",
420 | "description": "for",
421 | "scope": "text.html.twig"
422 | },
423 | "from": {
424 | "prefix": "from",
425 | "body": "{% from \"${1:template}\" import \"${2:macro}\" %}$0",
426 | "description": "from",
427 | "scope": "text.html.twig"
428 | },
429 | "endbody": {
430 | "prefix": "endbody",
431 | "body": "{{ endBody() }}\n$0",
432 | "description": "endBody",
433 | "scope": "text.html.twig"
434 | },
435 | "head": {
436 | "prefix": "head",
437 | "body": "{{ head() }}\n$0",
438 | "description": "head",
439 | "scope": "text.html.twig"
440 | },
441 | "if": {
442 | "prefix": "if",
443 | "body": "{% if ${1:condition} %}$2{% endif %}\n$0",
444 | "description": "if",
445 | "scope": "text.html.twig"
446 | },
447 | "ifb": {
448 | "prefix": "ifb",
449 | "body": "{% if ${1:condition} %}\n\t$0\n{% endif %}",
450 | "description": "if (block)",
451 | "scope": "text.html.twig"
452 | },
453 | "ife": {
454 | "prefix": "ife",
455 | "body": "{% if ${1:condition} %}\n\t$2\n{% else %}\n\t$0\n{% endif %}",
456 | "description": "if ... else",
457 | "scope": "text.html.twig"
458 | },
459 | "if1": {
460 | "prefix": "if",
461 | "body": "{% if ${1:condition} %}$0{% endif %}",
462 | "description": "if",
463 | "scope": "text.html.twig"
464 | },
465 | "ifchildren": {
466 | "prefix": "ifchildren",
467 | "body": "{% ifchildren %}\n\t$1\n{% endifchildren %}\n$0",
468 | "description": "ifchildren",
469 | "scope": "text.html.twig"
470 | },
471 | "import": {
472 | "prefix": "import",
473 | "body": "{% import \"${1:template}\" as ${2:name} %}$0",
474 | "description": "import",
475 | "scope": "text.html.twig"
476 | },
477 | "importself": {
478 | "prefix": "importself",
479 | "body": "{% import _self as ${1:name} %}$0",
480 | "description": "importself",
481 | "scope": "text.html.twig"
482 | },
483 | "inckv": {
484 | "prefix": "inckv",
485 | "body":
486 | "{% include \"${1:template}\" with {\n\t${2:key}: ${3:\"${4:value}\"}\n} %}\n$0",
487 | "description": "include w/ key/value",
488 | "scope": "text.html.twig"
489 | },
490 | "include": {
491 | "prefix": "include",
492 | "body": "{% include \"${1:template}\" %}$0",
493 | "description": "include",
494 | "scope": "text.html.twig"
495 | },
496 | "inc": {
497 | "prefix": "inc",
498 | "body": "{% include \"${1:template}\" %}$0",
499 | "description": "inc",
500 | "scope": "text.html.twig"
501 | },
502 | "incp": {
503 | "prefix": "incp",
504 | "body": "{% include \"${1:template}\"${2: with ${3:params} }%}$0",
505 | "description": "include w/ params",
506 | "scope": "text.html.twig"
507 | },
508 | "css1": {
509 | "prefix": "css",
510 | "body": "{% do view.registerCssFile(\"${1:/resources/css/global.css}\") %}\n$0",
511 | "description": "registerCssFile",
512 | "scope": "text.html.twig"
513 | },
514 | "js": {
515 | "prefix": "js",
516 | "body": "{% js %}\n\t$1\n{% endjs %}\n$0",
517 | "description": "js",
518 | "scope": "text.html.twig"
519 | },
520 | "js1": {
521 | "prefix": "js",
522 | "body": "{% do view.registerJsFile(\"${1:/resources/js/global.js}\") %}\n$0",
523 | "description": "registerJsFile",
524 | "scope": "text.html.twig"
525 | },
526 | "css": {
527 | "prefix": "css",
528 | "body": "{% css %}\n\t$1\n{% endcss %}\n$0",
529 | "description": "css",
530 | "scope": "text.html.twig"
531 | },
532 | "macro": {
533 | "prefix": "macro",
534 | "body": "{% macro ${1:name}(${2:params}) %}\n\t$0\n{% endmacro %}",
535 | "description": "macro",
536 | "scope": "text.html.twig"
537 | },
538 | "matrix": {
539 | "prefix": "matrix",
540 | "body":
541 | "{% 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",
542 | "description": "matrix",
543 | "scope": "text.html.twig"
544 | },
545 | "matrixif": {
546 | "prefix": "matrixif",
547 | "body":
548 | "{% 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",
549 | "description": "matrixif",
550 | "scope": "text.html.twig"
551 | },
552 | "matrixifelse": {
553 | "prefix": "matrixifelse",
554 | "body":
555 | "{% 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 %}",
556 | "description": "matrixifelse",
557 | "scope": "text.html.twig"
558 | },
559 | "matrixswitch": {
560 | "prefix": "matrixswitch",
561 | "body":
562 | "{% 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 %}",
563 | "description": "matrixswitch",
564 | "scope": "text.html.twig"
565 | },
566 | "max": {
567 | "prefix": "max",
568 | "body": "max(${1:$2, $3})$0",
569 | "description": "max",
570 | "scope": "text.html.twig"
571 | },
572 | "min": {
573 | "prefix": "min",
574 | "body": "min(${1:$2, $3})$0",
575 | "description": "min",
576 | "scope": "text.html.twig"
577 | },
578 | "nav": {
579 | "prefix": "nav",
580 | "body": "{% nav ${1:item} in ${2:items} %}\n\t$3\n{% endnav %}\n$0",
581 | "description": "nav",
582 | "scope": "text.html.twig"
583 | },
584 | "paginate": {
585 | "prefix": "paginate",
586 | "body":
587 | "{% 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 %}",
588 | "description": "paginate simple",
589 | "scope": "text.html.twig"
590 | },
591 | "paginate1": {
592 | "prefix": "paginate",
593 | "body":
594 | "{# 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\n\t{% if pageInfo.currentPage != \"1\" %}\n\t\t- First Page
\n\t{% endif %}\n\n\t{% if pageInfo.prevUrl %}\n\t\t- Previous Page
\n\t{% endif %}\n\n\t{% for pageNumber in 1..pageInfo.totalPages %}\n\t\t- \n\t\t\t{{ pageNumber }}\n\t\t
\n\t{% endfor %}\n\n\t{% if pageInfo.nextUrl %}\n\t\t- Next Page
\n\t{% endif %}\n\n\t{% if pageInfo.currentPage != pageInfo.total %}\n\t\t- Last Page
\n\t{% endif %}\n
\n{% endif %}\n$0",
595 | "description": "paginate advanced",
596 | "scope": "text.html.twig"
597 | },
598 | "redirect": {
599 | "prefix": "redirect",
600 | "body":
601 | "{% redirect \"${1:template/path or http://straightupcraft.com}\" %}\n$0",
602 | "description": "redirect",
603 | "scope": "text.html.twig"
604 | },
605 | "getparam": {
606 | "prefix": "getparam",
607 | "body":
608 | "craft.app.request.getParam(${1:\"Query String or Post Variable Name\"})\n$0",
609 | "description": "request getParam",
610 | "scope": "text.html.twig"
611 | },
612 | "getbodyparam": {
613 | "prefix": "getbodyparam",
614 | "body": "craft.app.request.getBodyParam(${1:\"postVariableName\"})\n$0",
615 | "description": "request getBodyParam",
616 | "scope": "text.html.twig"
617 | },
618 | "getqueryparam": {
619 | "prefix": "getqueryparam",
620 | "body": "craft.app.request.getQueryParam(${1:\"queryStringName\"})\n$0",
621 | "description": "request getQueryParam",
622 | "scope": "text.html.twig"
623 | },
624 | "getsegment": {
625 | "prefix": "getsegment",
626 | "body": "craft.app.request.getSegment(${1:2})\n$0",
627 | "description": "request getSegment",
628 | "scope": "text.html.twig"
629 | },
630 | "requirelogin": {
631 | "prefix": "requirelogin",
632 | "body": "{% requireLogin %}\n$0",
633 | "description": "requireLogin",
634 | "scope": "text.html.twig"
635 | },
636 | "requirepermission": {
637 | "prefix": "requirepermission",
638 | "body": "{% requirePermission \"${1:spendTheNight}\" %}\n$0",
639 | "description": "requirePermission",
640 | "scope": "text.html.twig"
641 | },
642 | "round": {
643 | "prefix": "round",
644 | "body": "{{ $1 | round(1, 'floor') }}$0",
645 | "description": "round",
646 | "scope": "text.html.twig"
647 | },
648 | "setb": {
649 | "prefix": "setb",
650 | "body": "{% set ${1:var} %}\n\t$0\n{% endset %}",
651 | "description": "set (block)",
652 | "scope": "text.html.twig"
653 | },
654 | "set": {
655 | "prefix": "set",
656 | "body": "{% set ${1:var} = ${2:value} %}$0",
657 | "description": "set",
658 | "scope": "text.html.twig"
659 | },
660 | "shuffle": {
661 | "prefix": "shuffle",
662 | "body": "shuffle($1)$0",
663 | "description": "shuffle",
664 | "scope": "text.html.twig"
665 | },
666 | "random": {
667 | "prefix": "random",
668 | "body": "random($1)$0",
669 | "description": "random",
670 | "scope": "text.html.twig"
671 | },
672 | "spaceless": {
673 | "prefix": "spaceless",
674 | "body": "{% spaceless %}\n\t$0\n{% endspaceless %}",
675 | "description": "spaceless",
676 | "scope": "text.html.twig"
677 | },
678 | "switch": {
679 | "prefix": "switch",
680 | "body":
681 | "{% switch ${1:variable} %}\n\n\t{% case \"${2:value1}\" %}\n\t\n\n\t{% case \"${3:value2}\" %}\n\t\n\n\t{% default %}\n\t\n\n{% endswitch %}\n$0",
682 | "description": "switch",
683 | "scope": "text.html.twig"
684 | },
685 | "trans": {
686 | "prefix": "trans",
687 | "body": "{% trans %}$0{% endtrans %}",
688 | "description": "trans",
689 | "scope": "text.html.twig"
690 | },
691 | "urla": {
692 | "prefix": "urla",
693 | "body":
694 | "url(\"${1:path}\", ${2:{foo:\"1\", bar:\"2\"\\}}, ${3:\"http\"}, ${4:false})$0",
695 | "description": "url w/ arguments",
696 | "scope": "text.html.twig"
697 | },
698 | "url": {
699 | "prefix": "url",
700 | "body": "url(\"${1:path}\")$0",
701 | "description": "url",
702 | "scope": "text.html.twig"
703 | },
704 | "use": {
705 | "prefix": "use",
706 | "body": "{% use \"${1:template}\" %}$0",
707 | "description": "use",
708 | "scope": "text.html.twig"
709 | },
710 | "verbatim": {
711 | "prefix": "verbatim",
712 | "body": "{% verbatim %}\n\t$0\n{% endverbatim %}",
713 | "description": "verbatim",
714 | "scope": "text.html.twig"
715 | }
716 | }
717 |
--------------------------------------------------------------------------------
/src/syntaxes/twig.tmLanguage:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fileTypes
6 |
7 | twig
8 | html.twig
9 |
10 | firstLineMatch
11 | <!(?i:DOCTYPE)|<(?i:html)|<\?(?i:php)|\{\{|\{%|\{#
12 | foldingStartMarker
13 | (?x)
14 | (<(?i:body|div|dl|fieldset|form|head|li|ol|script|select|style|table|tbody|tfoot|thead|tr|ul)\b.*?>
15 | |<!--(?!.*--\s*>)
16 | |^<!--\ \#tminclude\ (?>.*?-->)$
17 | |\{%\s+(autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim)
18 | )
19 | foldingStopMarker
20 | (?x)
21 | (</(?i:body|div|dl|fieldset|form|head|li|ol|script|select|style|table|tbody|tfoot|thead|tr|ul)>
22 | |^(?!.*?<!--).*?--\s*>
23 | |^<!--\ end\ tminclude\ -->$
24 | |\{%\s+end(autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim)
25 | )
26 | keyEquivalent
27 | ^~T
28 | name
29 | HTML (Twig)
30 | patterns
31 |
32 |
33 | begin
34 | (<)([a-zA-Z0-9:]++)(?=[^>]*></\2>)
35 | beginCaptures
36 |
37 | 1
38 |
39 | name
40 | punctuation.definition.tag.html
41 |
42 | 2
43 |
44 | name
45 | entity.name.tag.html
46 |
47 |
48 | end
49 | (>(<)/)(\2)(>)
50 | endCaptures
51 |
52 | 1
53 |
54 | name
55 | punctuation.definition.tag.html
56 |
57 | 2
58 |
59 | name
60 | meta.scope.between-tag-pair.html
61 |
62 | 3
63 |
64 | name
65 | entity.name.tag.html
66 |
67 | 4
68 |
69 | name
70 | punctuation.definition.tag.html
71 |
72 |
73 | name
74 | meta.tag.any.html
75 | patterns
76 |
77 |
78 | include
79 | #tag-stuff
80 |
81 |
82 |
83 |
84 | begin
85 | (<\?)(xml)
86 | captures
87 |
88 | 1
89 |
90 | name
91 | punctuation.definition.tag.html
92 |
93 | 2
94 |
95 | name
96 | entity.name.tag.xml.html
97 |
98 |
99 | end
100 | (\?>)
101 | name
102 | meta.tag.preprocessor.xml.html
103 | patterns
104 |
105 |
106 | include
107 | #tag-generic-attribute
108 |
109 |
110 | include
111 | #string-double-quoted
112 |
113 |
114 | include
115 | #string-single-quoted
116 |
117 |
118 |
119 |
120 | begin
121 | <!--
122 | captures
123 |
124 | 0
125 |
126 | name
127 | punctuation.definition.comment.html
128 |
129 |
130 | end
131 | --\s*>
132 | name
133 | comment.block.html
134 | patterns
135 |
136 |
137 | match
138 | --
139 | name
140 | invalid.illegal.bad-comments-or-CDATA.html
141 |
142 |
143 | include
144 | #embedded-code
145 |
146 |
147 |
148 |
149 | begin
150 | <!
151 | captures
152 |
153 | 0
154 |
155 | name
156 | punctuation.definition.tag.html
157 |
158 |
159 | end
160 | >
161 | name
162 | meta.tag.sgml.html
163 | patterns
164 |
165 |
166 | begin
167 | (?i:DOCTYPE)
168 | captures
169 |
170 | 1
171 |
172 | name
173 | entity.name.tag.doctype.html
174 |
175 |
176 | end
177 | (?=>)
178 | name
179 | meta.tag.sgml.doctype.html
180 | patterns
181 |
182 |
183 | match
184 | "[^">]*"
185 | name
186 | string.quoted.double.doctype.identifiers-and-DTDs.html
187 |
188 |
189 |
190 |
191 | begin
192 | \[CDATA\[
193 | end
194 | ]](?=>)
195 | name
196 | constant.other.inline-data.html
197 |
198 |
199 | match
200 | (\s*)(?!--|>)\S(\s*)
201 | name
202 | invalid.illegal.bad-comments-or-CDATA.html
203 |
204 |
205 |
206 |
207 | include
208 | #embedded-code
209 |
210 |
211 | begin
212 | (?:^\s+)?(<)((?i:style))\b(?![^>]*/>)
213 | captures
214 |
215 | 1
216 |
217 | name
218 | punctuation.definition.tag.html
219 |
220 | 2
221 |
222 | name
223 | entity.name.tag.style.html
224 |
225 | 3
226 |
227 | name
228 | punctuation.definition.tag.html
229 |
230 |
231 | end
232 | (</)((?i:style))(>)(?:\s*\n)?
233 | name
234 | source.css.embedded.html
235 | patterns
236 |
237 |
238 | include
239 | #tag-stuff
240 |
241 |
242 | begin
243 | (>)
244 | beginCaptures
245 |
246 | 1
247 |
248 | name
249 | punctuation.definition.tag.html
250 |
251 |
252 | end
253 | (?=</(?i:style))
254 | patterns
255 |
256 |
257 | include
258 | #embedded-code
259 |
260 |
261 | include
262 | source.css
263 |
264 |
265 |
266 |
267 |
268 |
269 | begin
270 | (?:^\s+)?(<)((?i:script))\b(?![^>]*/>)
271 | beginCaptures
272 |
273 | 1
274 |
275 | name
276 | punctuation.definition.tag.html
277 |
278 | 2
279 |
280 | name
281 | entity.name.tag.script.html
282 |
283 |
284 | end
285 | (?<=</(script|SCRIPT))(>)(?:\s*\n)?
286 | endCaptures
287 |
288 | 2
289 |
290 | name
291 | punctuation.definition.tag.html
292 |
293 |
294 | name
295 | source.js.embedded.html
296 | patterns
297 |
298 |
299 | include
300 | #tag-stuff
301 |
302 |
303 | begin
304 | (?<!</(?:script|SCRIPT))(>)
305 | captures
306 |
307 | 1
308 |
309 | name
310 | punctuation.definition.tag.html
311 |
312 | 2
313 |
314 | name
315 | entity.name.tag.script.html
316 |
317 |
318 | end
319 | (</)((?i:script))
320 | patterns
321 |
322 |
323 | captures
324 |
325 | 1
326 |
327 | name
328 | punctuation.definition.comment.js
329 |
330 |
331 | match
332 | (//).*?((?=</script)|$\n?)
333 | name
334 | comment.line.double-slash.js
335 |
336 |
337 | begin
338 | /\*
339 | captures
340 |
341 | 0
342 |
343 | name
344 | punctuation.definition.comment.js
345 |
346 |
347 | end
348 | \*/|(?=</script)
349 | name
350 | comment.block.js
351 |
352 |
353 | include
354 | #php
355 |
356 |
357 |
358 |
359 | include
360 | #twig-print-tag
361 |
362 |
363 | include
364 | #twig-statement-tag
365 |
366 |
367 | include
368 | #twig-comment-tag
369 |
370 |
371 |
372 |
373 | include
374 | source.js
375 |
376 |
377 |
378 |
379 |
380 |
381 | begin
382 | (?ix) # Enable free spacing mode, case insensitive
383 | # Make sure our opening js tag has word boundaries
384 | (?<=\{\%\sjs\s\%\}|\{\%\sincludejs\s\%\})
385 |
386 | comment
387 | Add JS support to set tags that use the pattern "css" in their name
388 | end
389 | (?ix)(?=\{\%\sendjs\s\%\}|\{\%\sendincludejs\s\%\})
390 | name
391 | source.js.embedded.twig
392 | patterns
393 |
394 |
395 | include
396 | source.js
397 |
398 |
399 |
400 |
401 | begin
402 | (?ix) # Enable free spacing mode, case insensitive
403 | (?<=\{\%\scss\s\%\}|\{\%\sincludecss\s\%\}|\{\%\sincludehirescss\s\%\})
404 |
405 | comment
406 | Add CSS support to set tags that use the pattern "css" in their name
407 | end
408 | (?ix)(?=\{\%\sendcss\s\%\}|\{\%\sendincludecss\s\%\}|\{\%\sendincludehirescss\s\%\})
409 | name
410 | source.css.embedded.twig
411 | patterns
412 |
413 |
414 | include
415 | source.css
416 |
417 |
418 |
419 |
420 | begin
421 | (?ix) # Enable free spacing mode, case insensitive
422 | (?<=\{\%\sscss\s\%\}|\{\%\sincludescss\s\%\}|\{\%\sincludehiresscss\s\%\})
423 |
424 | comment
425 | Add SCSS support to set tags that use the pattern "scss" in their name
426 | end
427 | (?ix)(?=\{\%\sendscss\s\%\}|\{\%\sendincludescss\s\%\}|\{\%\sendincludehiresscss\s\%\})
428 | name
429 | source.css.scss.embedded.twig
430 | patterns
431 |
432 |
433 | include
434 | source.css.scss
435 |
436 |
437 |
438 |
439 | begin
440 | (</?)((?i:body|head|html)\b)
441 | captures
442 |
443 | 1
444 |
445 | name
446 | punctuation.definition.tag.html
447 |
448 | 2
449 |
450 | name
451 | entity.name.tag.structure.any.html
452 |
453 |
454 | end
455 | (>)
456 | name
457 | meta.tag.structure.any.html
458 | patterns
459 |
460 |
461 | include
462 | #tag-stuff
463 |
464 |
465 |
466 |
467 | begin
468 | (</?)((?i:address|blockquote|dd|div|dl|dt|fieldset|form|frame|frameset|h1|h2|h3|h4|h5|h6|iframe|noframes|object|ol|p|ul|applet|center|dir|hr|menu|pre)\b)
469 | beginCaptures
470 |
471 | 1
472 |
473 | name
474 | punctuation.definition.tag.begin.html
475 |
476 | 2
477 |
478 | name
479 | entity.name.tag.block.any.html
480 |
481 |
482 | end
483 | (>)
484 | endCaptures
485 |
486 | 1
487 |
488 | name
489 | punctuation.definition.tag.end.html
490 |
491 |
492 | name
493 | meta.tag.block.any.html
494 | patterns
495 |
496 |
497 | include
498 | #tag-stuff
499 |
500 |
501 |
502 |
503 | begin
504 | (</?)((?i:a|abbr|acronym|area|b|base|basefont|bdo|big|br|button|caption|cite|code|col|colgroup|del|dfn|em|font|head|html|i|img|input|ins|isindex|kbd|label|legend|li|link|map|meta|noscript|optgroup|option|param|q|s|samp|script|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|u|var)\b)
505 | beginCaptures
506 |
507 | 1
508 |
509 | name
510 | punctuation.definition.tag.begin.html
511 |
512 | 2
513 |
514 | name
515 | entity.name.tag.inline.any.html
516 |
517 |
518 | end
519 | ((?: ?/)?>)
520 | endCaptures
521 |
522 | 1
523 |
524 | name
525 | punctuation.definition.tag.end.html
526 |
527 |
528 | name
529 | meta.tag.inline.any.html
530 | patterns
531 |
532 |
533 | include
534 | #tag-stuff
535 |
536 |
537 |
538 |
539 | begin
540 | (</?)([a-zA-Z0-9:]+)
541 | beginCaptures
542 |
543 | 1
544 |
545 | name
546 | punctuation.definition.tag.begin.html
547 |
548 | 2
549 |
550 | name
551 | entity.name.tag.other.html
552 |
553 |
554 | end
555 | (>)
556 | endCaptures
557 |
558 | 1
559 |
560 | name
561 | punctuation.definition.tag.end.html
562 |
563 |
564 | name
565 | meta.tag.other.html
566 | patterns
567 |
568 |
569 | include
570 | #tag-stuff
571 |
572 |
573 |
574 |
575 | include
576 | #entities
577 |
578 |
579 | match
580 | <>
581 | name
582 | invalid.illegal.incomplete.html
583 |
584 |
585 | match
586 | <
587 | name
588 | invalid.illegal.bad-angle-bracket.html
589 |
590 |
591 |
592 |
593 | include
594 | #twig-print-tag
595 |
596 |
597 | include
598 | #twig-statement-tag
599 |
600 |
601 | include
602 | #twig-comment-tag
603 |
604 |
605 |
606 | repository
607 |
608 | embedded-code
609 |
610 | patterns
611 |
612 |
613 | include
614 | #ruby
615 |
616 |
617 | include
618 | #php
619 |
620 |
621 |
622 |
623 | include
624 | #twig-print-tag
625 |
626 |
627 | include
628 | #twig-statement-tag
629 |
630 |
631 | include
632 | #twig-comment-tag
633 |
634 |
635 |
636 |
637 | include
638 | #python
639 |
640 |
641 |
642 | entities
643 |
644 | patterns
645 |
646 |
647 | captures
648 |
649 | 1
650 |
651 | name
652 | punctuation.definition.entity.html
653 |
654 | 3
655 |
656 | name
657 | punctuation.definition.entity.html
658 |
659 |
660 | match
661 | (&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)
662 | name
663 | constant.character.entity.html
664 |
665 |
666 | match
667 | &
668 | name
669 | invalid.illegal.bad-ampersand.html
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 | twig-print-tag
678 |
679 | begin
680 | \{\{-?
681 | beginCaptures
682 |
683 | 0
684 |
685 | name
686 | punctuation.section.tag.twig
687 |
688 |
689 | end
690 | -?\}\}
691 | endCaptures
692 |
693 | 0
694 |
695 | name
696 | punctuation.section.tag.twig
697 |
698 |
699 | name
700 | meta.tag.template.value.twig
701 | patterns
702 |
703 |
704 | include
705 | #twig-constants
706 |
707 |
708 | include
709 | #twig-operators
710 |
711 |
712 | include
713 | #twig-functions-warg
714 |
715 |
716 | include
717 | #twig-functions
718 |
719 |
720 | include
721 | #twig-macros
722 |
723 |
724 | include
725 | #twig-objects
726 |
727 |
728 | include
729 | #twig-properties
730 |
731 |
732 | include
733 | #twig-filters-warg
734 |
735 |
736 | include
737 | #twig-filters
738 |
739 |
740 | include
741 | #twig-filters-warg-ud
742 |
743 |
744 | include
745 | #twig-filters-ud
746 |
747 |
748 | include
749 | #twig-strings
750 |
751 |
752 | include
753 | #twig-arrays
754 |
755 |
756 | include
757 | #twig-hashes
758 |
759 |
760 |
761 |
762 |
763 | twig-statement-tag
764 |
765 | begin
766 | \{%-?
767 | beginCaptures
768 |
769 | 0
770 |
771 | name
772 | punctuation.section.tag.twig
773 |
774 |
775 | end
776 | -?%\}
777 | endCaptures
778 |
779 | 0
780 |
781 | name
782 | punctuation.section.tag.twig
783 |
784 |
785 | name
786 | meta.tag.template.block.twig
787 | patterns
788 |
789 |
790 | include
791 | #twig-constants
792 |
793 |
794 | include
795 | #twig-keywords
796 |
797 |
798 | include
799 | #twig-operators
800 |
801 |
802 | include
803 | #twig-functions-warg
804 |
805 |
806 | include
807 | #twig-functions
808 |
809 |
810 | include
811 | #twig-macros
812 |
813 |
814 | include
815 | #twig-filters-warg
816 |
817 |
818 | include
819 | #twig-filters
820 |
821 |
822 | include
823 | #twig-filters-warg-ud
824 |
825 |
826 | include
827 | #twig-filters-ud
828 |
829 |
830 | include
831 | #twig-objects
832 |
833 |
834 | include
835 | #twig-properties
836 |
837 |
838 | include
839 | #twig-strings
840 |
841 |
842 | include
843 | #twig-arrays
844 |
845 |
846 | include
847 | #twig-hashes
848 |
849 |
850 |
851 |
852 |
853 | twig-comment-tag
854 |
855 | begin
856 | \{#-?
857 | beginCaptures
858 |
859 | 0
860 |
861 | name
862 | punctuation.definition.comment.begin.twig
863 |
864 |
865 | end
866 | -?#\}
867 | endCaptures
868 |
869 | 0
870 |
871 | name
872 | punctuation.definition.comment.end.twig
873 |
874 |
875 | name
876 | comment.block.twig
877 |
878 |
879 |
880 | twig-constants
881 |
882 | patterns
883 |
884 |
885 |
886 | match
887 | (?i)(?<=[\s\[\(\{:,])(?:true|false|null|none)(?=[\s\)\]\}\,])
888 | name
889 | constant.language.twig
890 |
891 |
892 |
893 | match
894 | (?<=[\s\[\(\{:,]|\.\.|\*\*)[0-9]+(?:\.[0-9]+)?(?=[\s\)\]\}\,]|\.\.|\*\*)
895 | name
896 | constant.numeric.twig
897 |
898 |
899 |
900 |
901 |
902 | twig-operators
903 |
904 | patterns
905 |
906 |
907 |
908 | captures
909 |
910 | 1
911 |
912 | name
913 | keyword.operator.arithmetic.twig
914 |
915 |
916 | match
917 | (?<=\s)(\+|-|//?|%|\*\*?)(?=\s)
918 |
919 |
920 |
921 |
922 | captures
923 |
924 | 1
925 |
926 | name
927 | keyword.operator.assignment.twig
928 |
929 |
930 | match
931 | (?<=\s)(=|~)(?=\s)
932 |
933 |
934 |
935 |
936 | captures
937 |
938 | 1
939 |
940 | name
941 | keyword.operator.bitwise.twig
942 |
943 |
944 | match
945 | (?<=\s)(b-(?:and|or|xor))(?=\s)
946 |
947 |
948 |
949 |
950 | captures
951 |
952 | 1
953 |
954 | name
955 | keyword.operator.comparison.twig
956 |
957 |
958 | match
959 | (?<=\s)((?:!|=)=|<=?|>=?|(?:not )?in|is(?: not)?|(?:ends|starts) with|matches)(?=\s)
960 |
961 |
962 |
963 |
964 | captures
965 |
966 | 1
967 |
968 | name
969 | keyword.operator.logical.twig
970 |
971 |
972 | match
973 | (?<=\s)(\?|:|\?:|\?\?|and|not|or)(?=\s)
974 |
975 |
976 |
977 |
978 | captures
979 |
980 | 0
981 |
982 | name
983 | keyword.operator.other.twig
984 |
985 |
986 | match
987 | (?<=[a-zA-Z0-9_\x{7f}-\x{ff}\]\)'"])\.\.(?=[a-zA-Z0-9_\x{7f}-\x{ff}'"])
988 |
989 |
990 |
991 |
992 | captures
993 |
994 | 0
995 |
996 | name
997 | keyword.operator.other.twig
998 |
999 |
1000 | match
1001 | (?<=[a-zA-Z0-9_\x{7f}-\x{ff}\]\}\)'"])\|(?=[a-zA-Z_\x{7f}-\x{ff}])
1002 |
1003 |
1004 |
1005 |
1006 |
1007 | twig-objects
1008 |
1009 | captures
1010 |
1011 | 1
1012 |
1013 | name
1014 | variable.other.twig
1015 |
1016 |
1017 | match
1018 | (?<=[\s\{\[\(:,])([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(?=[\s\}\[\]\(\)\.\|,:])
1019 |
1020 |
1021 |
1022 | twig-properties
1023 |
1024 | patterns
1025 |
1026 |
1027 |
1028 | captures
1029 |
1030 | 1
1031 |
1032 | name
1033 | punctuation.separator.property.twig
1034 |
1035 | 2
1036 |
1037 | name
1038 | variable.other.property.twig
1039 |
1040 |
1041 | match
1042 | (?x)
1043 | (?<=[a-zA-Z0-9_\x{7f}-\x{ff}])
1044 | (\.)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
1045 | (?=[\.\s\|\[\)\]\}:,])
1046 |
1047 |
1048 |
1049 |
1050 |
1051 | begin
1052 | (?x)
1053 | (?<=[a-zA-Z0-9_\x{7f}-\x{ff}])
1054 | (\.)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
1055 | (\()
1056 |
1057 | beginCaptures
1058 |
1059 | 1
1060 |
1061 | name
1062 | punctuation.separator.property.twig
1063 |
1064 | 2
1065 |
1066 | name
1067 | variable.other.property.twig
1068 |
1069 | 3
1070 |
1071 | name
1072 | punctuation.definition.parameters.begin.twig
1073 |
1074 |
1075 | end
1076 | \)
1077 | endCaptures
1078 |
1079 | 0
1080 |
1081 | name
1082 | punctuation.definition.parameters.end.twig
1083 |
1084 |
1085 | patterns
1086 |
1087 |
1088 | include
1089 | #twig-constants
1090 |
1091 |
1092 | include
1093 | #twig-functions-warg
1094 |
1095 |
1096 | include
1097 | #twig-functions
1098 |
1099 |
1100 | include
1101 | #twig-macros
1102 |
1103 |
1104 | include
1105 | #twig-objects
1106 |
1107 |
1108 | include
1109 | #twig-properties
1110 |
1111 |
1112 | include
1113 | #twig-filters-warg
1114 |
1115 |
1116 | include
1117 | #twig-filters
1118 |
1119 |
1120 | include
1121 | #twig-filters-warg-ud
1122 |
1123 |
1124 | include
1125 | #twig-filters-ud
1126 |
1127 |
1128 | include
1129 | #twig-strings
1130 |
1131 |
1132 | include
1133 | #twig-arrays
1134 |
1135 |
1136 | contentName
1137 | meta.function.arguments.twig
1138 |
1139 |
1140 |
1141 |
1142 | captures
1143 |
1144 | 1
1145 |
1146 | name
1147 | punctuation.section.array.begin.twig
1148 |
1149 | 2
1150 |
1151 | name
1152 | variable.other.property.twig
1153 |
1154 | 3
1155 |
1156 | name
1157 | punctuation.section.array.end.twig
1158 |
1159 | 4
1160 |
1161 | name
1162 | punctuation.section.array.begin.twig
1163 |
1164 | 5
1165 |
1166 | name
1167 | variable.other.property.twig
1168 |
1169 | 6
1170 |
1171 | name
1172 | punctuation.section.array.end.twig
1173 |
1174 | 7
1175 |
1176 | name
1177 | punctuation.section.array.begin.twig
1178 |
1179 | 8
1180 |
1181 | name
1182 | variable.other.property.twig
1183 |
1184 | 9
1185 |
1186 | name
1187 | punctuation.section.array.end.twig
1188 |
1189 |
1190 | match
1191 | (?x)
1192 | (?<=[a-zA-Z0-9_\x{7f}-\x{ff}\]])
1193 | (?:
1194 | (\[)('[a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*')(\])
1195 | |(\[)("[a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*")(\])
1196 | |(\[)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(\])
1197 | )
1198 |
1199 |
1200 |
1201 |
1202 |
1203 |
1204 | twig-strings
1205 |
1206 | patterns
1207 |
1208 |
1209 |
1210 | begin
1211 | (?:(?<!\\)|(?<=\\\\))'
1212 | beginCaptures
1213 |
1214 | 0
1215 |
1216 | name
1217 | punctuation.definition.string.begin.twig
1218 |
1219 |
1220 | end
1221 | (?:(?<!\\)|(?<=\\\\))'
1222 | endCaptures
1223 |
1224 | 0
1225 |
1226 | name
1227 | punctuation.definition.string.end.twig
1228 |
1229 |
1230 | name
1231 | string.quoted.single.twig
1232 |
1233 |
1234 |
1235 |
1236 | begin
1237 | (?:(?<!\\)|(?<=\\\\))"
1238 | beginCaptures
1239 |
1240 | 0
1241 |
1242 | name
1243 | punctuation.definition.string.begin.twig
1244 |
1245 |
1246 | end
1247 | (?:(?<!\\)|(?<=\\\\))"
1248 | endCaptures
1249 |
1250 | 0
1251 |
1252 | name
1253 | punctuation.definition.string.end.twig
1254 |
1255 |
1256 | name
1257 | string.quoted.double.twig
1258 |
1259 |
1260 |
1261 |
1262 |
1263 | twig-arrays
1264 |
1265 | begin
1266 | (?<=[\s\(\{\[:,])\[
1267 | beginCaptures
1268 |
1269 | 0
1270 |
1271 | name
1272 | punctuation.section.array.begin.twig
1273 |
1274 |
1275 | end
1276 | \]
1277 | endCaptures
1278 |
1279 | 0
1280 |
1281 | name
1282 | punctuation.section.array.end.twig
1283 |
1284 |
1285 | patterns
1286 |
1287 |
1288 | include
1289 | #twig-arrays
1290 |
1291 |
1292 | include
1293 | #twig-hashes
1294 |
1295 |
1296 | include
1297 | #twig-constants
1298 |
1299 |
1300 | include
1301 | #twig-operators
1302 |
1303 |
1304 | include
1305 | #twig-strings
1306 |
1307 |
1308 | include
1309 | #twig-functions-warg
1310 |
1311 |
1312 | include
1313 | #twig-functions
1314 |
1315 |
1316 | include
1317 | #twig-macros
1318 |
1319 |
1320 | include
1321 | #twig-objects
1322 |
1323 |
1324 | include
1325 | #twig-properties
1326 |
1327 |
1328 | include
1329 | #twig-filters-warg
1330 |
1331 |
1332 | include
1333 | #twig-filters
1334 |
1335 |
1336 | include
1337 | #twig-filters-warg-ud
1338 |
1339 |
1340 | include
1341 | #twig-filters-ud
1342 |
1343 |
1344 | match
1345 | ,
1346 | name
1347 | punctuation.separator.object.twig
1348 |
1349 |
1350 | name
1351 | meta.array.twig
1352 |
1353 |
1354 |
1355 | twig-hashes
1356 |
1357 | begin
1358 | (?<=[\s\(\{\[:,])\{
1359 | beginCaptures
1360 |
1361 | 0
1362 |
1363 | name
1364 | punctuation.section.hash.begin.twig
1365 |
1366 |
1367 | end
1368 | \}
1369 | endCaptures
1370 |
1371 | 0
1372 |
1373 | name
1374 | punctuation.section.hash.end.twig
1375 |
1376 |
1377 | patterns
1378 |
1379 |
1380 | include
1381 | #twig-hashes
1382 |
1383 |
1384 | include
1385 | #twig-arrays
1386 |
1387 |
1388 | include
1389 | #twig-constants
1390 |
1391 |
1392 | include
1393 | #twig-operators
1394 |
1395 |
1396 | include
1397 | #twig-strings
1398 |
1399 |
1400 | include
1401 | #twig-functions-warg
1402 |
1403 |
1404 | include
1405 | #twig-functions
1406 |
1407 |
1408 | include
1409 | #twig-macros
1410 |
1411 |
1412 | include
1413 | #twig-objects
1414 |
1415 |
1416 | include
1417 | #twig-properties
1418 |
1419 |
1420 | include
1421 | #twig-filters-warg
1422 |
1423 |
1424 | include
1425 | #twig-filters
1426 |
1427 |
1428 | include
1429 | #twig-filters-warg-ud
1430 |
1431 |
1432 | include
1433 | #twig-filters-ud
1434 |
1435 |
1436 | match
1437 | :
1438 | name
1439 | punctuation.separator.key-value.twig
1440 |
1441 |
1442 | match
1443 | ,
1444 | name
1445 | punctuation.separator.object.twig
1446 |
1447 |
1448 | name
1449 | meta.hash.twig
1450 |
1451 |
1452 |
1453 | twig-keywords
1454 |
1455 | match
1456 | (?<=\s)((?:end)?(?:autoescape|block|embed|filter|for|if|macro|raw|sandbox|set|spaceless|trans|verbatim)|as|do|else|elseif|extends|flush|from|ignore missing|import|include|only|use|with)(?=\s)
1457 | name
1458 | keyword.control.twig
1459 |
1460 |
1461 |
1462 | twig-functions-warg
1463 |
1464 | begin
1465 | (?<=[\s\(\[\{:,])(attribute|block|constant|cycle|date|divisible by|dump|include|max|min|parent|random|range|same as|source|template_from_string)(\()
1466 | beginCaptures
1467 |
1468 | 1
1469 |
1470 | name
1471 | support.function.twig
1472 |
1473 | 2
1474 |
1475 | name
1476 | punctuation.definition.parameters.begin.twig
1477 |
1478 |
1479 | end
1480 | \)
1481 | endCaptures
1482 |
1483 | 0
1484 |
1485 | name
1486 | punctuation.definition.parameters.end.twig
1487 |
1488 |
1489 | patterns
1490 |
1491 |
1492 | include
1493 | #twig-constants
1494 |
1495 |
1496 | include
1497 | #twig-functions-warg
1498 |
1499 |
1500 | include
1501 | #twig-functions
1502 |
1503 |
1504 | include
1505 | #twig-macros
1506 |
1507 |
1508 | include
1509 | #twig-objects
1510 |
1511 |
1512 | include
1513 | #twig-properties
1514 |
1515 |
1516 | include
1517 | #twig-filters-warg
1518 |
1519 |
1520 | include
1521 | #twig-filters
1522 |
1523 |
1524 | include
1525 | #twig-filters-warg-ud
1526 |
1527 |
1528 | include
1529 | #twig-filters-ud
1530 |
1531 |
1532 | include
1533 | #twig-strings
1534 |
1535 |
1536 | include
1537 | #twig-arrays
1538 |
1539 |
1540 | contentName
1541 | meta.function.arguments.twig
1542 |
1543 |
1544 |
1545 | twig-functions
1546 |
1547 | captures
1548 |
1549 | 1
1550 |
1551 | name
1552 | support.function.twig
1553 |
1554 |
1555 | match
1556 | (?<=is\s)(defined|empty|even|iterable|odd)
1557 |
1558 |
1559 |
1560 | twig-macros
1561 |
1562 | begin
1563 | (?x)
1564 | (?<=[\s\(\[\{:,])
1565 | ([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
1566 | (?:
1567 | (\.)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
1568 | )?
1569 | (\()
1570 |
1571 | beginCaptures
1572 |
1573 | 1
1574 |
1575 | name
1576 | meta.function-call.twig
1577 |
1578 | 2
1579 |
1580 | name
1581 | punctuation.separator.property.twig
1582 |
1583 | 3
1584 |
1585 | name
1586 | variable.other.property.twig
1587 |
1588 | 4
1589 |
1590 | name
1591 | punctuation.definition.parameters.begin.twig
1592 |
1593 |
1594 | end
1595 | \)
1596 | endCaptures
1597 |
1598 | 0
1599 |
1600 | name
1601 | punctuation.definition.parameters.end.twig
1602 |
1603 |
1604 | patterns
1605 |
1606 |
1607 | include
1608 | #twig-constants
1609 |
1610 |
1611 | include
1612 | #twig-operators
1613 |
1614 |
1615 | include
1616 | #twig-functions-warg
1617 |
1618 |
1619 | include
1620 | #twig-functions
1621 |
1622 |
1623 | include
1624 | #twig-macros
1625 |
1626 |
1627 | include
1628 | #twig-objects
1629 |
1630 |
1631 | include
1632 | #twig-properties
1633 |
1634 |
1635 | include
1636 | #twig-filters-warg
1637 |
1638 |
1639 | include
1640 | #twig-filters
1641 |
1642 |
1643 | include
1644 | #twig-filters-warg-ud
1645 |
1646 |
1647 | include
1648 | #twig-filters-ud
1649 |
1650 |
1651 | include
1652 | #twig-strings
1653 |
1654 |
1655 | include
1656 | #twig-arrays
1657 |
1658 |
1659 | include
1660 | #twig-hashes
1661 |
1662 |
1663 | contentName
1664 | meta.function.arguments.twig
1665 |
1666 |
1667 |
1668 |
1669 | twig-filters-warg
1670 |
1671 | begin
1672 | (?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\'\"]\|)|\{%\sfilter\s)(batch|convert_encoding|date|date_modify|default|e(?:scape)?|format|join|merge|number_format|replace|round|slice|split|trim)(\()
1673 | beginCaptures
1674 |
1675 | 1
1676 |
1677 | name
1678 | support.function.twig
1679 |
1680 | 2
1681 |
1682 | name
1683 | punctuation.definition.parameters.begin.twig
1684 |
1685 |
1686 | end
1687 | \)
1688 | endCaptures
1689 |
1690 | 0
1691 |
1692 | name
1693 | punctuation.definition.parameters.end.twig
1694 |
1695 |
1696 | patterns
1697 |
1698 |
1699 | include
1700 | #twig-constants
1701 |
1702 |
1703 | include
1704 | #twig-operators
1705 |
1706 |
1707 | include
1708 | #twig-functions-warg
1709 |
1710 |
1711 | include
1712 | #twig-functions
1713 |
1714 |
1715 | include
1716 | #twig-macros
1717 |
1718 |
1719 | include
1720 | #twig-objects
1721 |
1722 |
1723 | include
1724 | #twig-properties
1725 |
1726 |
1727 | include
1728 | #twig-filters-warg
1729 |
1730 |
1731 | include
1732 | #twig-filters
1733 |
1734 |
1735 | include
1736 | #twig-filters-warg-ud
1737 |
1738 |
1739 | include
1740 | #twig-filters-ud
1741 |
1742 |
1743 | include
1744 | #twig-strings
1745 |
1746 |
1747 | include
1748 | #twig-arrays
1749 |
1750 |
1751 | include
1752 | #twig-hashes
1753 |
1754 |
1755 | contentName
1756 | meta.function.arguments.twig
1757 |
1758 |
1759 |
1760 | twig-filters
1761 |
1762 | captures
1763 |
1764 | 1
1765 |
1766 | name
1767 | support.function.twig
1768 |
1769 |
1770 | match
1771 | (?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\'\"]\|)|\{%\sfilter\s)(abs|capitalize|e(?:scape)?|first|join|(?:json|url)_encode|keys|last|length|lower|nl2br|number_format|raw|reverse|round|sort|striptags|title|trim|upper)(?=[\s\|\]\}\):,]|\.\.|\*\*)
1772 |
1773 |
1774 |
1775 | twig-filters-warg-ud
1776 |
1777 | begin
1778 | (?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\'\"]\|)|\{%\sfilter\s)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(\()
1779 | beginCaptures
1780 |
1781 | 1
1782 |
1783 | name
1784 | meta.function-call.other.twig
1785 |
1786 | 2
1787 |
1788 | name
1789 | punctuation.definition.parameters.begin.twig
1790 |
1791 |
1792 | end
1793 | \)
1794 | endCaptures
1795 |
1796 | 0
1797 |
1798 | name
1799 | punctuation.definition.parameters.end.twig
1800 |
1801 |
1802 | patterns
1803 |
1804 |
1805 | include
1806 | #twig-constants
1807 |
1808 |
1809 | include
1810 | #twig-functions-warg
1811 |
1812 |
1813 | include
1814 | #twig-functions
1815 |
1816 |
1817 | include
1818 | #twig-macros
1819 |
1820 |
1821 | include
1822 | #twig-objects
1823 |
1824 |
1825 | include
1826 | #twig-properties
1827 |
1828 |
1829 | include
1830 | #twig-filters-warg
1831 |
1832 |
1833 | include
1834 | #twig-filters
1835 |
1836 |
1837 | include
1838 | #twig-filters-warg-ud
1839 |
1840 |
1841 | include
1842 | #twig-filters-ud
1843 |
1844 |
1845 | include
1846 | #twig-strings
1847 |
1848 |
1849 | include
1850 | #twig-arrays
1851 |
1852 |
1853 | include
1854 | #twig-hashes
1855 |
1856 |
1857 | contentName
1858 | meta.function.arguments.twig
1859 |
1860 |
1861 |
1862 | twig-filters-ud
1863 |
1864 | captures
1865 |
1866 | 1
1867 |
1868 | name
1869 | meta.function-call.other.twig
1870 |
1871 |
1872 | match
1873 | (?<=(?:[a-zA-Z0-9_\x{7f}-\x{ff}\]\)\'\"]\|)|\{%\sfilter\s)([a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)
1874 |
1875 |
1876 |
1877 |
1878 | php
1879 |
1880 | begin
1881 | (?=(^\s*)?<\?)
1882 | end
1883 | (?!(^\s*)?<\?)
1884 | patterns
1885 |
1886 |
1887 | include
1888 | source.php
1889 |
1890 |
1891 |
1892 | python
1893 |
1894 | begin
1895 | (?:^\s*)<\?python(?!.*\?>)
1896 | end
1897 | \?>(?:\s*$\n)?
1898 | name
1899 | source.python.embedded.html
1900 | patterns
1901 |
1902 |
1903 | include
1904 | source.python
1905 |
1906 |
1907 |
1908 | ruby
1909 |
1910 | patterns
1911 |
1912 |
1913 | begin
1914 | <%+#
1915 | captures
1916 |
1917 | 0
1918 |
1919 | name
1920 | punctuation.definition.comment.erb
1921 |
1922 |
1923 | end
1924 | %>
1925 | name
1926 | comment.block.erb
1927 |
1928 |
1929 | begin
1930 | <%+(?!>)=?
1931 | captures
1932 |
1933 | 0
1934 |
1935 | name
1936 | punctuation.section.embedded.ruby
1937 |
1938 |
1939 | end
1940 | -?%>
1941 | name
1942 | source.ruby.embedded.html
1943 | patterns
1944 |
1945 |
1946 | captures
1947 |
1948 | 1
1949 |
1950 | name
1951 | punctuation.definition.comment.ruby
1952 |
1953 |
1954 | match
1955 | (#).*?(?=-?%>)
1956 | name
1957 | comment.line.number-sign.ruby
1958 |
1959 |
1960 | include
1961 | source.ruby
1962 |
1963 |
1964 |
1965 |
1966 | begin
1967 | <\?r(?!>)=?
1968 | captures
1969 |
1970 | 0
1971 |
1972 | name
1973 | punctuation.section.embedded.ruby.nitro
1974 |
1975 |
1976 | end
1977 | -?\?>
1978 | name
1979 | source.ruby.nitro.embedded.html
1980 | patterns
1981 |
1982 |
1983 | captures
1984 |
1985 | 1
1986 |
1987 | name
1988 | punctuation.definition.comment.ruby.nitro
1989 |
1990 |
1991 | match
1992 | (#).*?(?=-?\?>)
1993 | name
1994 | comment.line.number-sign.ruby.nitro
1995 |
1996 |
1997 | include
1998 | source.ruby
1999 |
2000 |
2001 |
2002 |
2003 |
2004 | string-double-quoted
2005 |
2006 | begin
2007 | "
2008 | beginCaptures
2009 |
2010 | 0
2011 |
2012 | name
2013 | punctuation.definition.string.begin.html
2014 |
2015 |
2016 | end
2017 | "
2018 | endCaptures
2019 |
2020 | 0
2021 |
2022 | name
2023 | punctuation.definition.string.end.html
2024 |
2025 |
2026 | name
2027 | string.quoted.double.html
2028 | patterns
2029 |
2030 |
2031 | include
2032 | #embedded-code
2033 |
2034 |
2035 | include
2036 | #entities
2037 |
2038 |
2039 |
2040 | string-single-quoted
2041 |
2042 | begin
2043 | '
2044 | beginCaptures
2045 |
2046 | 0
2047 |
2048 | name
2049 | punctuation.definition.string.begin.html
2050 |
2051 |
2052 | end
2053 | '
2054 | endCaptures
2055 |
2056 | 0
2057 |
2058 | name
2059 | punctuation.definition.string.end.html
2060 |
2061 |
2062 | name
2063 | string.quoted.single.html
2064 | patterns
2065 |
2066 |
2067 | include
2068 | #embedded-code
2069 |
2070 |
2071 | include
2072 | #entities
2073 |
2074 |
2075 |
2076 | tag-generic-attribute
2077 |
2078 | match
2079 | \b([a-zA-Z\-:]+)
2080 | name
2081 | entity.other.attribute-name.html
2082 |
2083 | tag-id-attribute
2084 |
2085 | begin
2086 | \b(id)\b\s*(=)
2087 | captures
2088 |
2089 | 1
2090 |
2091 | name
2092 | entity.other.attribute-name.id.html
2093 |
2094 | 2
2095 |
2096 | name
2097 | punctuation.separator.key-value.html
2098 |
2099 |
2100 | end
2101 | (?<='|")
2102 | name
2103 | meta.attribute-with-value.id.html
2104 | patterns
2105 |
2106 |
2107 | begin
2108 | "
2109 | beginCaptures
2110 |
2111 | 0
2112 |
2113 | name
2114 | punctuation.definition.string.begin.html
2115 |
2116 |
2117 | contentName
2118 | meta.toc-list.id.html
2119 | end
2120 | "
2121 | endCaptures
2122 |
2123 | 0
2124 |
2125 | name
2126 | punctuation.definition.string.end.html
2127 |
2128 |
2129 | name
2130 | string.quoted.double.html
2131 | patterns
2132 |
2133 |
2134 | include
2135 | #embedded-code
2136 |
2137 |
2138 | include
2139 | #entities
2140 |
2141 |
2142 |
2143 |
2144 | begin
2145 | '
2146 | beginCaptures
2147 |
2148 | 0
2149 |
2150 | name
2151 | punctuation.definition.string.begin.html
2152 |
2153 |
2154 | contentName
2155 | meta.toc-list.id.html
2156 | end
2157 | '
2158 | endCaptures
2159 |
2160 | 0
2161 |
2162 | name
2163 | punctuation.definition.string.end.html
2164 |
2165 |
2166 | name
2167 | string.quoted.single.html
2168 | patterns
2169 |
2170 |
2171 | include
2172 | #embedded-code
2173 |
2174 |
2175 | include
2176 | #entities
2177 |
2178 |
2179 |
2180 |
2181 |
2182 | tag-stuff
2183 |
2184 | patterns
2185 |
2186 |
2187 | include
2188 | #tag-id-attribute
2189 |
2190 |
2191 | include
2192 | #tag-generic-attribute
2193 |
2194 |
2195 | include
2196 | #string-double-quoted
2197 |
2198 |
2199 | include
2200 | #string-single-quoted
2201 |
2202 |
2203 | include
2204 | #embedded-code
2205 |
2206 |
2207 |
2208 |
2209 | scopeName
2210 | text.html.twig
2211 | uuid
2212 | C220B028-86FF-44CB-8A59-27937FC83730
2213 |
2214 |
2215 |
--------------------------------------------------------------------------------