├── .gitignore ├── Comments.tmPreferences ├── HTML (Liquid).sublime-settings ├── Snippets ├── assign.sublime-snippet ├── capture.sublime-snippet ├── comment.sublime-snippet ├── context_variable.sublime-snippet ├── cycle.sublime-snippet ├── else.sublime-snippet ├── elsif.sublime-snippet ├── endcapture.sublime-snippet ├── endfor.sublime-snippet ├── endif.sublime-snippet ├── endraw.sublime-snippet ├── for.sublime-snippet ├── if.sublime-snippet ├── ife.sublime-snippet ├── ifelse.sublime-snippet ├── inc.sublime-snippet ├── include.sublime-snippet ├── tag.sublime-snippet └── unless.sublime-snippet ├── Syntaxes ├── HTML (Liquid).YAML-tmLanguage └── HTML (Liquid).tmLanguage ├── liquid.sublime-completions └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.cache 3 | *.sublime-project -------------------------------------------------------------------------------- /Comments.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Preferences 7 | scope 8 | text.html.liquid 9 | settings 10 | 11 | shellVariables 12 | 13 | 14 | name 15 | TM_COMMENT_START 16 | value 17 | {% comment %} 18 | 19 | 20 | name 21 | TM_COMMENT_END 22 | value 23 | {% endcomment %} 24 | 25 | 26 | name 27 | TM_COMMENT_MODE 28 | value 29 | block 30 | 31 | 32 | 33 | uuid 34 | A3452E24-5C3A-42AF-B7D4-1C509BEEB638 35 | 36 | 37 | -------------------------------------------------------------------------------- /HTML (Liquid).sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "extensions": 3 | [ 4 | "liquid" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /Snippets/assign.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | assign 5 | text.html.liquid 6 | assign 7 | -------------------------------------------------------------------------------- /Snippets/capture.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | capture 5 | text.html.liquid 6 | capture 7 | -------------------------------------------------------------------------------- /Snippets/comment.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | comment 5 | text.html.liquid 6 | comment 7 | -------------------------------------------------------------------------------- /Snippets/context_variable.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | va 5 | text.html.liquid 6 | context variable (var) 7 | -------------------------------------------------------------------------------- /Snippets/cycle.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | cycle 5 | text.html.liquid 6 | cycle 7 | -------------------------------------------------------------------------------- /Snippets/else.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | else 5 | text.html.liquid 6 | else 7 | -------------------------------------------------------------------------------- /Snippets/elsif.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | elsif 5 | text.html.liquid 6 | elsif 7 | -------------------------------------------------------------------------------- /Snippets/endcapture.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | endcapture 5 | text.html.liquid 6 | endcapture 7 | -------------------------------------------------------------------------------- /Snippets/endfor.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | endfor 5 | text.html.liquid 6 | endfor 7 | -------------------------------------------------------------------------------- /Snippets/endif.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | endif 5 | text.html.liquid 6 | endif 7 | -------------------------------------------------------------------------------- /Snippets/endraw.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | endraw 5 | text.html.liquid 6 | endraw 7 | -------------------------------------------------------------------------------- /Snippets/for.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | for 9 | text.html.liquid 10 | for 11 | -------------------------------------------------------------------------------- /Snippets/if.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | % 7 | text.html.liquid 8 | tag 9 | -------------------------------------------------------------------------------- /Snippets/ife.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | ife 11 | text.html.liquid 12 | if... else... 13 | -------------------------------------------------------------------------------- /Snippets/ifelse.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | ifelse 11 | text.html.liquid 12 | if... else... 13 | -------------------------------------------------------------------------------- /Snippets/inc.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | inc 5 | text.html.liquid 6 | include (inc) 7 | -------------------------------------------------------------------------------- /Snippets/include.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | include 5 | text.html.liquid 6 | include 7 | -------------------------------------------------------------------------------- /Snippets/tag.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | if 9 | text.html.liquid 10 | if 11 | -------------------------------------------------------------------------------- /Snippets/unless.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | unless 9 | text.html.liquid 10 | unless 11 | -------------------------------------------------------------------------------- /Syntaxes/HTML (Liquid).YAML-tmLanguage: -------------------------------------------------------------------------------- 1 | # [PackageDev] target_format: plist, ext: tmLanguage 2 | name: HTML (Liquid) 3 | scopeName: text.html.liquid 4 | fileTypes: [liquid] 5 | uuid: f2a39460-98fd-11e1-a8b0-0800200c9a66 6 | 7 | patterns: 8 | - name: comment.block.liquid 9 | begin: '{%-?\s*comment\s*-?%}' 10 | end: '{%-?\s*endcomment\s*-?%}' 11 | 12 | - name: punctuation.output.liquid 13 | begin: '{{-?' 14 | end: '-?}}' 15 | patterns: 16 | - include: '#template_var' 17 | 18 | - name: punctuation.tag.liquid 19 | begin: '{%-?' 20 | end: '-?%}' 21 | patterns: 22 | - include: '#template_tag_name' 23 | - include: '#template_var' 24 | 25 | - include: text.html.basic 26 | 27 | repository: 28 | assign_op: 29 | patterns: 30 | - name: keyword.operator.assignment.augmented.liquid 31 | match: /= 32 | 33 | logic_expression: 34 | patterns: 35 | - match: /= 36 | name: keyword.operator.assignment.augmented.liquid 37 | 38 | logic_op: 39 | patterns: 40 | - name: keyword.operator.logical.liquid 41 | match: \s+(and|or|not|contains|(\!\=|\=\=|<\=|>\=|<|>)\s+ 42 | template_tag_name: 43 | patterns: 44 | - name: entity.name.tag.liquid 45 | match: (?<={%)\s*(\w+) 46 | - name: entity.name.tag.liquid 47 | match: (?<={%-)\s*(\w+) 48 | template_var: 49 | patterns: 50 | - match: (\[)(\|)(?=[^\]]*)(?=\]) 51 | captures: 52 | '2': {name: invalid.illegal.filter.liquid} 53 | '3': {name: invalid.illegal.filter.liquid} 54 | - name: invalid.illegal.filter.liquid 55 | match: (?<=\s)(\+|\-|\/|\*)(?=\s) 56 | - name: constant.language.liquid 57 | match: (false|true|nil) 58 | - match: (?=if|unless|elsif)\s*[^%}]+\s(in)\s 59 | captures: 60 | '3': {name: invalid.illegal.operator.liquid} 61 | - name: keyword.operator.liquid 62 | match: \s+(and|or|not|contains|in|by|((\!|\=|\<|\>)\=))\s+ 63 | - match: (?<=assign)([^\=]+)(\=\=+) 64 | captures: 65 | '2': {name: invalid.illegal.assignment.liquid} 66 | - name: support.function.with-args.liquid 67 | match: \|\s+(?![\.0-9])[a-zA-Z0-9_-]+\:\s+ 68 | - name: support.function.without-args.liquid 69 | match: \|\s+(?![\.0-9])[a-zA-Z0-9_-]+\s+ 70 | - name: keyword.control.liquid 71 | match: (?<=\s)(with|offset\:|limit\:)(?=\s) 72 | - match: (?<=include)(.*)(with\:|offset|limit)(?=\s) 73 | captures: 74 | '2': {name: invalid.illegal.argument.liquid} 75 | - name: invalid.illegal.liquid 76 | match: (?<=\s)(\w+\:)(?=\:\s) 77 | - name: string.quoted.double.liquid 78 | begin: '"' 79 | end: '"' 80 | - name: string.quoted.single.liquid 81 | begin: '''' 82 | end: '''' 83 | - name: constant.numeric.liquid 84 | match: (-|\+)?\s*[0-9]+(\.[0-9]+)? 85 | - name: support.class.liquid 86 | match: \b(collection|product|linklist|linklists|order|link|customer|customer_address|line_item|shop|collections|page_title|template|image|blog|blogs|cart|pages|theme|themes|variant|items|comment|forloop|settings)\b 87 | - name: support.class.liquid 88 | match: \b(assets|author|body|body_raw|current|date|excerpt_raw|meta|next|pages|parent|posts|previous|site|tags|taxonomy|title|url)\b 89 | - name: variable.parameter.liquid 90 | match: ((?<=\w\:\s)\w+) 91 | - name: support.variable.liquid 92 | match: (?<=\.)\w+\b 93 | - name: variable.other.liquid 94 | match: \w+ 95 | foldingStartMarker: (?x){%\s*(if|unless|for|paginate|capture|form|case|tablerow|raw|comment)[^(%})]+%} 96 | foldingStopMarker: (?x){%\s*(endif|endunless|endfor|endpaginate|endcapture|endform|endcase|endtablerow|endraw|endcomment)[^(%})]+%} 97 | -------------------------------------------------------------------------------- /Syntaxes/HTML (Liquid).tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | fileTypes 6 | 7 | liquid 8 | 9 | foldingStartMarker 10 | (?x){%\s*(if|unless|for|paginate|capture|form|case|tablerow|raw|comment)[^(%})]+%} 11 | foldingStopMarker 12 | (?x){%\s*(endif|endunless|endfor|endpaginate|endcapture|endform|endcase|endtablerow|endraw|endcomment)[^(%})]+%} 13 | name 14 | HTML (Liquid) 15 | patterns 16 | 17 | 18 | begin 19 | {%-?\s*comment\s*-?%} 20 | end 21 | {%-?\s*endcomment\s*-?%} 22 | name 23 | comment.block.liquid 24 | 25 | 26 | begin 27 | {{-? 28 | end 29 | -?}} 30 | name 31 | punctuation.output.liquid 32 | patterns 33 | 34 | 35 | include 36 | #template_var 37 | 38 | 39 | 40 | 41 | begin 42 | {%-? 43 | end 44 | -?%} 45 | name 46 | punctuation.tag.liquid 47 | patterns 48 | 49 | 50 | include 51 | #template_tag_name 52 | 53 | 54 | include 55 | #template_var 56 | 57 | 58 | 59 | 60 | include 61 | text.html.basic 62 | 63 | 64 | repository 65 | 66 | assign_op 67 | 68 | patterns 69 | 70 | 71 | match 72 | /= 73 | name 74 | keyword.operator.assignment.augmented.liquid 75 | 76 | 77 | 78 | logic_expression 79 | 80 | patterns 81 | 82 | 83 | match 84 | /= 85 | name 86 | keyword.operator.assignment.augmented.liquid 87 | 88 | 89 | 90 | logic_op 91 | 92 | patterns 93 | 94 | 95 | match 96 | \s+(and|or|not|contains|(\!\=|\=\=|<\=|>\=|<|>)\s+ 97 | name 98 | keyword.operator.logical.liquid 99 | 100 | 101 | 102 | template_tag_name 103 | 104 | patterns 105 | 106 | 107 | match 108 | (?<={%)\s*(\w+) 109 | name 110 | entity.name.tag.liquid 111 | 112 | 113 | match 114 | (?<={%-)\s*(\w+) 115 | name 116 | entity.name.tag.liquid 117 | 118 | 119 | 120 | template_var 121 | 122 | patterns 123 | 124 | 125 | captures 126 | 127 | 2 128 | 129 | name 130 | invalid.illegal.filter.liquid 131 | 132 | 3 133 | 134 | name 135 | invalid.illegal.filter.liquid 136 | 137 | 138 | match 139 | (\[)(\|)(?=[^\]]*)(?=\]) 140 | 141 | 142 | match 143 | (?<=\s)(\+|\-|\/|\*)(?=\s) 144 | name 145 | invalid.illegal.filter.liquid 146 | 147 | 148 | match 149 | (false|true|nil) 150 | name 151 | constant.language.liquid 152 | 153 | 154 | captures 155 | 156 | 3 157 | 158 | name 159 | invalid.illegal.operator.liquid 160 | 161 | 162 | match 163 | (?=if|unless|elsif)\s*[^%}]+\s(in)\s 164 | 165 | 166 | match 167 | \s+(and|or|not|contains|in|by|((\!|\=|\<|\>)\=))\s+ 168 | name 169 | keyword.operator.liquid 170 | 171 | 172 | captures 173 | 174 | 2 175 | 176 | name 177 | invalid.illegal.assignment.liquid 178 | 179 | 180 | match 181 | (?<=assign)([^\=]+)(\=\=+) 182 | 183 | 184 | match 185 | \|\s+(?![\.0-9])[a-zA-Z0-9_-]+\:\s+ 186 | name 187 | support.function.with-args.liquid 188 | 189 | 190 | match 191 | \|\s+(?![\.0-9])[a-zA-Z0-9_-]+\s+ 192 | name 193 | support.function.without-args.liquid 194 | 195 | 196 | match 197 | (?<=\s)(with|offset\:|limit\:)(?=\s) 198 | name 199 | keyword.control.liquid 200 | 201 | 202 | captures 203 | 204 | 2 205 | 206 | name 207 | invalid.illegal.argument.liquid 208 | 209 | 210 | match 211 | (?<=include)(.*)(with\:|offset|limit)(?=\s) 212 | 213 | 214 | match 215 | (?<=\s)(\w+\:)(?=\:\s) 216 | name 217 | invalid.illegal.liquid 218 | 219 | 220 | begin 221 | " 222 | end 223 | " 224 | name 225 | string.quoted.double.liquid 226 | 227 | 228 | begin 229 | ' 230 | end 231 | ' 232 | name 233 | string.quoted.single.liquid 234 | 235 | 236 | match 237 | (-|\+)?\s*[0-9]+(\.[0-9]+)? 238 | name 239 | constant.numeric.liquid 240 | 241 | 242 | match 243 | \b(collection|product|linklist|linklists|order|link|customer|customer_address|line_item|shop|collections|page_title|template|image|blog|blogs|cart|pages|theme|themes|variant|items|comment|forloop|settings)\b 244 | name 245 | support.class.liquid 246 | 247 | 248 | match 249 | \b(assets|author|body|body_raw|current|date|excerpt_raw|meta|next|pages|parent|posts|previous|site|tags|taxonomy|title|url)\b 250 | name 251 | support.class.liquid 252 | 253 | 254 | match 255 | ((?<=\w\:\s)\w+) 256 | name 257 | variable.parameter.liquid 258 | 259 | 260 | match 261 | (?<=\.)\w+\b 262 | name 263 | support.variable.liquid 264 | 265 | 266 | match 267 | \w+ 268 | name 269 | variable.other.liquid 270 | 271 | 272 | 273 | 274 | scopeName 275 | text.html.liquid 276 | uuid 277 | f2a39460-98fd-11e1-a8b0-0800200c9a66 278 | 279 | 280 | -------------------------------------------------------------------------------- /liquid.sublime-completions: -------------------------------------------------------------------------------- 1 | { 2 | "scope": "text.html.liquid punctuation.output.liquid, text.html.liquid punctuation.tag.liquid, text.html.liquid support.class.liquid", 3 | 4 | "completions": 5 | [ 6 | { "trigger": "assets.date", "contents": "assets.date" }, 7 | { "trigger": "assets.type", "contents": "assets.type" }, 8 | { "trigger": "assets.filename", "contents": "assets.filename" }, 9 | { "trigger": "assets.url", "contents": "assets.url" }, 10 | { "trigger": "assets.permalink", "contents": "assets.permalink" }, 11 | { "trigger": "assets.content_type", "contents": "assets.content_type" }, 12 | { "trigger": "assets.file", "contents": "assets.file" }, 13 | 14 | { "trigger": "site.date", "contents": "site.date" }, 15 | { "trigger": "site.domain", "contents": "site.domain" }, 16 | { "trigger": "site.feed_url", "contents": "site.feed_url" }, 17 | { "trigger": "site.pages", "contents": "site.pages" }, 18 | { "trigger": "site.permalink", "contents": "site.permalink" }, 19 | { "trigger": "site.posts", "contents": "site.posts" }, 20 | { "trigger": "site.sitemap_url", "contents": "site.sitemap_url" }, 21 | 22 | { "trigger": "trim", "contents": "replace: \" \", split: \" \" | join: \" \""}, 23 | { "trigger": "img_tag", "contents": "img_tag" }, 24 | { "trigger": "script_tag", "contents": "script_tag" }, 25 | { "trigger": "stylesheet_tag", "contents": "stylesheet_tag" }, 26 | { "trigger": "link_to", "contents": "link_to" }, 27 | { "trigger": "money_with_currency", "contents": "money_with_currency" }, 28 | { "trigger": "money_without_currency", "contents": "money_without_currency" }, 29 | { "trigger": "money", "contents": "money" }, 30 | { "trigger": "plus", "contents": "plus" }, 31 | { "trigger": "minus", "contents": "minus" }, 32 | { "trigger": "times", "contents": "times" }, 33 | { "trigger": "divided_by", "contents": "divided_by" }, 34 | { "trigger": "append", "contents": "append: " }, 35 | { "trigger": "camelize", "contents": "camelize" }, 36 | { "trigger": "capitalize", "contents": "capitalize" }, 37 | { "trigger": "date", "contents": "date" }, 38 | { "trigger": "downcase", "contents": "downcase" }, 39 | { "trigger": "escape", "contents": "escape" }, 40 | { "trigger": "first", "contents": "first" }, 41 | { "trigger": "handleize", "contents": "handleize" }, 42 | { "trigger": "highlight_active_tag", "contents": "highlight_active_tag" }, 43 | { "trigger": "join", "contents": "join" }, 44 | { "trigger": "last", "contents": "last" }, 45 | { "trigger": "replace_first", "contents": "replace_first: $0" }, 46 | { "trigger": "remove", "contents": "remove" }, 47 | { "trigger": "remove_first", "contents": "remove_first: $0" }, 48 | { "trigger": "newline_to_br", "contents": "newline_to_br" }, 49 | { "trigger": "pluralize", "contents": "pluralize" }, 50 | { "trigger": "prepend", "contents": "prepend" }, 51 | { "trigger": "size", "contents": "size" }, 52 | { "trigger": "split", "contents": "split: $0" }, 53 | { "trigger": "strip_html", "contents": "strip_html" }, 54 | { "trigger": "strip_newlines", "contents": "strip_newlines" }, 55 | { "trigger": "replace", "contents": "replace" }, 56 | { "trigger": "truncate", "contents": "truncate" }, 57 | { "trigger": "truncatewords", "contents": "truncatewords" }, 58 | { "trigger": "upcase", "contents": "upcase" }, 59 | { "trigger": "weight_with_unit", "contents": "weight_with_unit" }, 60 | { "trigger": "json", "contents": "json" } 61 | ] 62 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Siteleaf Liquid support for Sublime Text 2 | 3 | This is a fork of the [shopify-liquid](https://bitbucket.org/granteagon/shopify-liquid) syntax, which was based off of the Djaniero package for Django. 4 | 5 | ## Installation 6 | 7 | **Suggested**: Install using [Package Control](https://packagecontrol.io/). Search for "Siteleaf Liquid Syntax". 8 | 9 | **Or** install manually: 10 | 11 | 1. Clone this repo 12 | 2. Put the contents of this repo directly inside: 13 | 14 | - OS X: ~/Library/Application Support/Sublime Text 3/Packages/ 15 | - Windows: %APPDATA%/Sublime Text 3/Packages/ 16 | - Linux: ~/.config/sublime-text-3/Packages 17 | 18 | **After installing:** 19 | 20 | You might need to switch to the syntax mode. (`shift + cmd + p`, search for Liquid, "Set Syntax: HTML (Liquid)") 21 | 22 | ## Autocomplete 23 | 24 | To show the autocomplete suggestions, your cursor must be within a tag markup or output marker wrapper (`{% %}` or `{{ }}`) 25 | 26 | Then press `ctrl + spacebar`, or add the following to your user settings file: 27 | 28 | ``` 29 | "auto_complete_selector": "source - comment, text.html.liquid punctuation.output.liquid, text.html.liquid punctuation.tag.liquid" 30 | ``` 31 | 32 | ## Snippets 33 | 34 | Some handy snippets: 35 | 36 | **IF statement** 37 | 38 | ``` 39 | if + tab >>> 40 | 41 | {% if $1 %} 42 | $2 43 | {% endif %} 44 | ``` 45 | 46 | **Tag markup** 47 | 48 | ``` 49 | % + tab >>> 50 | 51 | {% $1 %} 52 | ``` 53 | 54 | **Assign** 55 | 56 | ``` 57 | assign + tab >>> 58 | 59 | {% assign $1 = $2 %} 60 | ``` 61 | 62 | **Capture** 63 | 64 | ``` 65 | capture + tab >>> 66 | 67 | {% capture $1 %}$2{% endcapture %} 68 | ``` 69 | 70 | **Comment** 71 | 72 | ``` 73 | comment + tab >>> 74 | 75 | {% comment %}$0{% endcomment %} 76 | ``` 77 | 78 | **Context variable** 79 | 80 | ``` 81 | va + tab >>> 82 | 83 | {{ $1 }} 84 | ``` 85 | 86 | **Cycle** 87 | 88 | ``` 89 | cycle + tab >>> 90 | 91 | {% cycle $1 %} 92 | ``` 93 | 94 | **Else** 95 | 96 | ``` 97 | else + tab >>> 98 | 99 | {% else %} 100 | ``` 101 | 102 | **Elsif** 103 | 104 | ``` 105 | elsif + tab >>> 106 | 107 | {% elsif $1 %} 108 | ``` 109 | 110 | **Endcapture** 111 | 112 | ``` 113 | endcapture + tab >>> 114 | 115 | {% endcapture %} 116 | ``` 117 | 118 | **Endfor** 119 | 120 | ``` 121 | endfor + tab >>> 122 | 123 | {% endfor %} 124 | ``` 125 | 126 | **Endif** 127 | 128 | ``` 129 | endif + tab >>> 130 | 131 | {% endif %} 132 | ``` 133 | 134 | **Endraw** 135 | 136 | ``` 137 | endraw + tab >>> 138 | 139 | {% endraw %} 140 | ``` 141 | 142 | **For** 143 | 144 | ``` 145 | for + tab >>> 146 | 147 | {% for $1 in $2 %} 148 | $3 149 | {% endfor %} 150 | ``` 151 | 152 | For a full list, check out the "Snippets" folder. 153 | --------------------------------------------------------------------------------