diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..98fccd6 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.8 \ No newline at end of file diff --git a/README.md b/README.md index e49c74e..efde56a 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,36 @@ # Vue Syntax Highlight +**Note**: the `st4` branch hosts the new syntax that only works in Sublime build > 4107. + +* For Sublime Text 2 support (`.tmlanguage` files), see `master` branch. +* For Sublime Text 3 support, see `new` branch. + Sublime Text Syntax highlighting for single-file [Vue.js](http://vuejs.org) components (enabled by [vue-loader](https://github.com/vuejs/vue-loader) or [vueify](https://github.com/vuejs/vueify)). -![screenshot](https://cloud.githubusercontent.com/assets/499550/11458853/99ed23aa-9696-11e5-9bf6-43c706487aee.png) +

+ +

### Install - Via Package Control: search for `Vue Syntax Highlight`. - Manual: clone this repo into your Sublime `Packages` folder. -**NOTE:** You still need to install corresponding packages for pre-processors (e.g. Jade, SASS, CoffeeScript) to get proper syntax highlighting for them. +**NOTE:** You still need to install corresponding packages for pre-processors (e.g. Pug, SASS, CoffeeScript) to get proper syntax highlighting for them. ### Enabling JSX Highlighting -The ` tag + (?: (\s*) (-->) \s* )? (?=) \s* $ + ) + style_content_begin: '{{script_content_begin}}' + style_content_end: |- + (?x: + # optional html comment end punctuation followed by tag + (?: (\s*) (-->) \s* )? (?=) \s* $ + ) + template_content_begin: '{{script_content_begin}}' + template_content_end: |- + (?x: + # optional html comment end punctuation followed by tag + (?: (\s*) (-->) \s* )? (?=) \s* $ + ) + +contexts: + +###[ HTML TAGS ]############################################################## + + prototype: + - meta_prepend: true + - include: mustache-templates + + tag-html: + - meta_prepend: true + - include: script-tag + - include: style-tag + - include: template-tag + +###[ SCRIPT TAG ]############################################################# + + script-tag: + # for compatibility with ST builds before 4114 + - match: (<)((?i:script)){{tag_name_break}} + captures: + 1: punctuation.definition.tag.begin.html + 2: entity.name.tag.script.html + push: script-javascript + - match: (' + scope: punctuation.definition.tag.end.html + set: script-javascript-content + - include: script-common + + script-javascript-content: + # for compatibility with ST builds before 4114 + - meta_include_prototype: false + - match: '{{script_content_begin}}' + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 # make sure to match only once + embed: scope:source.js + embed_scope: source.js.embedded.html + escape: '{{script_content_end}}' + escape_captures: + 1: source.js.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.js.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + + script-lang-attribute: + - match: (?i:lang){{attribute_name_break}} + scope: meta.attribute-with-value.html entity.other.attribute-name.html + set: script-lang-attribute-assignment + + script-lang-attribute-assignment: + - meta_content_scope: meta.tag.script.begin.html meta.attribute-with-value.html + - match: = + scope: punctuation.separator.key-value.html + set: script-lang-attribute-value + - match: (?=\S) + set: script-javascript + + script-lang-attribute-value: + - meta_include_prototype: false + - meta_scope: meta.tag.script.begin.html meta.attribute-with-value.html + - include: script-lang-decider + + script-lang-decider: + - match: (?i)(?=coffee{{unquoted_attribute_break}}|\'coffee\'|"coffee") + set: + - - meta_scope: meta.tag.script.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{script_content_begin}}' + embed_scope: source.coffee.embedded.html + escape_captures: + 1: source.coffee.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.coffee.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.coffee + escape: '{{script_content_end}}' + - include: script-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=livescript{{unquoted_attribute_break}}|\'livescript\'|"livescript") + set: + - - meta_scope: meta.tag.script.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{script_content_begin}}' + embed_scope: source.livescript.embedded.html + escape_captures: + 1: source.livescript.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.livescript.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.livescript + escape: '{{script_content_end}}' + - include: script-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=ts{{unquoted_attribute_break}}|\'ts\'|"ts") + set: + - - meta_scope: meta.tag.script.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{script_content_begin}}' + embed_scope: source.ts.embedded.html + escape_captures: + 1: source.ts.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.ts.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.ts + escape: '{{script_content_end}}' + - include: script-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?=\S) + set: + - script-javascript + - tag-generic-attribute-meta + - tag-generic-attribute-value + +###[ STYLE TAG ]############################################################## + + style-tag: + # for compatibility with ST builds before 4114 + - match: (<)((?i:style)){{tag_name_break}} + captures: + 1: punctuation.definition.tag.begin.html + 2: entity.name.tag.style.html + push: style-css + - match: (' + scope: punctuation.definition.tag.end.html + set: style-css-content + - include: style-common + + style-css-content: + # for compatibility with ST builds before 4114 + - meta_include_prototype: false + - match: '{{style_content_begin}}' + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 # make sure to match only once + embed: scope:source.css + embed_scope: source.css.embedded.html + escape: '{{style_content_end}}' + escape_captures: + 1: source.css.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.css.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + + style-lang-attribute: + - match: (?i:lang){{attribute_name_break}} + scope: meta.attribute-with-value.html entity.other.attribute-name.html + set: style-lang-attribute-assignment + + style-lang-attribute-assignment: + - meta_content_scope: meta.tag.style.begin.html meta.attribute-with-value.html + - match: = + scope: punctuation.separator.key-value.html + set: style-lang-attribute-value + - match: (?=\S) + set: style-css + + style-lang-attribute-value: + - meta_include_prototype: false + - meta_scope: meta.tag.style.begin.html meta.attribute-with-value.html + - include: style-lang-decider + + style-lang-decider: + - match: (?i)(?=sass{{unquoted_attribute_break}}|\'sass\'|"sass") + set: + - - meta_scope: meta.tag.style.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{style_content_begin}}' + embed_scope: source.sass.embedded.html + escape_captures: + 1: source.sass.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.sass.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.sass + escape: '{{style_content_end}}' + - include: style-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=scss{{unquoted_attribute_break}}|\'scss\'|"scss") + set: + - - meta_scope: meta.tag.style.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{style_content_begin}}' + embed_scope: source.scss.embedded.html + escape_captures: + 1: source.scss.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.scss.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.scss + escape: '{{style_content_end}}' + - include: style-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=stylus{{unquoted_attribute_break}}|\'stylus\'|"stylus") + set: + - - meta_scope: meta.tag.style.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{style_content_begin}}' + embed_scope: source.stylus.embedded.html + escape_captures: + 1: source.stylus.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.stylus.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.stylus + escape: '{{style_content_end}}' + - include: style-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=postcss\?parser=sugarss{{unquoted_attribute_break}}|\'postcss\?parser=sugarss\'|"postcss\?parser=sugarss") + set: + - - meta_scope: meta.tag.style.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{style_content_begin}}' + embed_scope: source.sss.embedded.html + escape_captures: + 1: source.sss.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.sss.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.sss + escape: '{{style_content_end}}' + - include: style-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=postcss{{unquoted_attribute_break}}|\'postcss\'|"postcss") + set: + - - meta_scope: meta.tag.style.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{style_content_begin}}' + embed_scope: source.postcss.embedded.html + escape_captures: + 1: source.postcss.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.postcss.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.postcss + escape: '{{style_content_end}}' + - include: style-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=less{{unquoted_attribute_break}}|\'less\'|"less") + set: + - - meta_scope: meta.tag.style.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{style_content_begin}}' + embed_scope: source.less.embedded.html + escape_captures: + 1: source.less.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.less.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:source.less + escape: '{{style_content_end}}' + - include: style-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?=\S) + set: + - style-css + - tag-generic-attribute-meta + - tag-generic-attribute-value + +###[ TEMPLATE TAG ]########################################################### + + template-tag: + - match: (<)((?i:template)){{tag_name_break}} + captures: + 1: punctuation.definition.tag.begin.html + 2: entity.name.tag.template.html + push: template-mustache + - match: (' + scope: punctuation.definition.tag.end.html + set: + - match: '{{template_content_begin}}' + embed_scope: text.jade.embedded.html + escape_captures: + 1: text.jade.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: text.jade.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:text.jade + escape: '{{template_content_end}}' + - include: template-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=pug{{unquoted_attribute_break}}|\'pug\'|"pug") + set: + - - meta_scope: meta.tag.template.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{template_content_begin}}' + embed_scope: text.pug.embedded.html + escape_captures: + 1: text.pug.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: text.pug.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:text.pug + escape: '{{template_content_end}}' + - include: template-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?i)(?=slm{{unquoted_attribute_break}}|\'slm\'|"slm") + set: + - - meta_scope: meta.tag.template.begin.html + - match: '>' + scope: punctuation.definition.tag.end.html + set: + - match: '{{template_content_begin}}' + embed_scope: text.slm.embedded.html + escape_captures: + 1: text.slm.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: text.slm.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 + embed: scope:text.slm + escape: '{{template_content_end}}' + - include: template-common + - tag-generic-attribute-meta + - tag-generic-attribute-value + - match: (?=\S) + set: + - template-mustache + - tag-generic-attribute-meta + - tag-generic-attribute-value + +###[ TAG ATTRIBUTES ]######################################################### + + tag-attributes: + - meta_prepend: true + - include: vue-directive + + tag-class-attribute-value: + # for compatibility with ST builds before 4114 + - meta_prepend: true + - meta_include_prototype: false + + tag-generic-attribute-value: + # for compatibility with ST builds before 4114 + - meta_prepend: true + - meta_include_prototype: false + + tag-href-attribute-value: + # for compatibility with ST builds before 4114 + - meta_prepend: true + - meta_include_prototype: false + + tag-id-attribute-value: + # for compatibility with ST builds before 4114 + - meta_prepend: true + - meta_include_prototype: false + + tag-attribute-value-content: + - meta_prepend: true + - include: mustache-interpolations + + strings-common-content: + - meta_prepend: true + - include: mustache-interpolations + +###[ MUSTAGE TEMPLATES ]###################################################### + + mustache-interpolations: + - match: (?={{) + push: mustache-interpolation-content + + mustache-interpolation-content: + - clear_scopes: 1 + - include: mustache-templates + - include: immediately-pop + + mustache-templates: + - match: '{{' + scope: meta.interpolation.vue punctuation.definition.interpolation.begin.html + embed: scope:source.js + embed_scope: meta.interpolation.vue source.js.embedded.vue + escape: '}}' + escape_captures: + 0: meta.interpolation.vue punctuation.definition.interpolation.end.html + +###[ VUE DIRECTIVES ]######################################################### + + vue-directive: + - match: (?=v-) + push: + - vue-directive-meta + - vue-directive-assignment + - tag-generic-attribute-name + - match: (?::|@|#) + scope: punctuation.definition.attribute.html + push: + - vue-directive-meta + - vue-directive-assignment + - tag-generic-attribute-name + + vue-directive-meta: + - meta_include_prototype: false + - meta_scope: meta.attribute-with-value.directive.html + - include: immediately-pop + + vue-directive-assignment: + - match: = + scope: punctuation.separator.key-value.html + set: vue-directive-value + - include: else-pop + + vue-directive-value: + - match: \" + scope: meta.string.html string.quoted.double.html punctuation.definition.string.begin.html + embed: scope:source.js#expression-statement + embed_scope: meta.string.html meta.interpolation.vue source.js.embedded.vue + escape: \" + escape_captures: + 0: meta.attribute-with-value.directive.html meta.string.html string.quoted.double.html + punctuation.definition.string.end.html + - match: \' + scope: meta.string.html string.quoted.single.html punctuation.definition.string.begin.html + embed: scope:source.js#expression-statement + embed_scope: meta.string.html meta.interpolation.vue source.js.embedded.vue + escape: \' + escape_captures: + 0: meta.attribute-with-value.directive.html meta.string.html string.quoted.single.html + punctuation.definition.string.end.html + - include: else-pop + + tag-generic-attribute-name: + - meta_prepend: true + # https://vuejs.org/guide/essentials/template-syntax.html#dynamic-arguments + - match: (?=\[) + push: vue-dynamic-attribute-name + + vue-dynamic-attribute-name: + - clear_scopes: 1 # clear `entity.other.attribute-name` + - match: \[ + scope: meta.interpolation.vue punctuation.section.interpolation.begin.vue + embed: scope:source.js#expression-statement + embed_scope: meta.interpolation.vue source.js.embedded.vue + escape: \] + escape_captures: + 0: meta.interpolation.vue punctuation.definition.interpolation.end.vue + - include: immediately-pop diff --git a/Vue Component.sublime-syntax.yaml-macros b/Vue Component.sublime-syntax.yaml-macros new file mode 100644 index 0000000..6daadfb --- /dev/null +++ b/Vue Component.sublime-syntax.yaml-macros @@ -0,0 +1,405 @@ +%YAML 1.2 +%TAG ! tag:yaml-macros:src.macros: +--- +name: Vue Component +scope: text.html.vue +version: 2 + +extends: Packages/HTML/HTML.sublime-syntax + +file_extensions: + - vue + +variables: + # Embedded script and style syntaxes may be wrapped into html comments for + # historical reasons. The following patterns match them, while maintaining + # correct boundaries of embedded source scopes. That's required to enable + # embedded syntax's comment toggling in the first and last line. + # + # see: + # - https://github.com/sublimehq/Packages/issues/2322 + # - https://github.com/sublimehq/sublime_text/issues/4701 + script_content_begin: |- + (?x: + # whitespace followed by opening html comment begin punctuation + \s*() \s* )? (?=) \s* $ + ) + style_content_begin: '{{script_content_begin}}' + style_content_end: |- + (?x: + # optional html comment end punctuation followed by tag + (?: (\s*) (-->) \s* )? (?=) \s* $ + ) + template_content_begin: '{{script_content_begin}}' + template_content_end: |- + (?x: + # optional html comment end punctuation followed by tag + (?: (\s*) (-->) \s* )? (?=) \s* $ + ) + +contexts: + +###[ HTML TAGS ]############################################################## + + prototype: + - meta_prepend: true + - include: mustache-templates + + tag-html: + - meta_prepend: true + - include: script-tag + - include: style-tag + - include: template-tag + +###[ SCRIPT TAG ]############################################################# + + script-tag: + # for compatibility with ST builds before 4114 + - match: (<)((?i:script)){{tag_name_break}} + captures: + 1: punctuation.definition.tag.begin.html + 2: entity.name.tag.script.html + push: script-javascript + - match: (' + scope: punctuation.definition.tag.end.html + set: script-javascript-content + - include: script-common + + script-javascript-content: + # for compatibility with ST builds before 4114 + - meta_include_prototype: false + - match: '{{script_content_begin}}' + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 # make sure to match only once + embed: scope:source.js + embed_scope: source.js.embedded.html + escape: '{{script_content_end}}' + escape_captures: + 1: source.js.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.js.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + + script-lang-attribute: + - match: (?i:lang){{attribute_name_break}} + scope: meta.attribute-with-value.html entity.other.attribute-name.html + set: script-lang-attribute-assignment + + script-lang-attribute-assignment: + - meta_content_scope: meta.tag.script.begin.html meta.attribute-with-value.html + - match: = + scope: punctuation.separator.key-value.html + set: script-lang-attribute-value + - match: (?=\S) + set: script-javascript + + script-lang-attribute-value: + - meta_include_prototype: false + - meta_scope: meta.tag.script.begin.html meta.attribute-with-value.html + - include: script-lang-decider + + script-lang-decider: + - !script_language [ coffee, source.coffee ] + - !script_language [ livescript, source.livescript ] + - !script_language [ ts, source.ts ] + - match: (?=\S) + set: + - script-javascript + - tag-generic-attribute-meta + - tag-generic-attribute-value + +###[ STYLE TAG ]############################################################## + + style-tag: + # for compatibility with ST builds before 4114 + - match: (<)((?i:style)){{tag_name_break}} + captures: + 1: punctuation.definition.tag.begin.html + 2: entity.name.tag.style.html + push: style-css + - match: (' + scope: punctuation.definition.tag.end.html + set: style-css-content + - include: style-common + + style-css-content: + # for compatibility with ST builds before 4114 + - meta_include_prototype: false + - match: '{{style_content_begin}}' + captures: + 1: comment.block.html punctuation.definition.comment.begin.html + pop: 1 # make sure to match only once + embed: scope:source.css + embed_scope: source.css.embedded.html + escape: '{{style_content_end}}' + escape_captures: + 1: source.css.embedded.html + 2: comment.block.html punctuation.definition.comment.end.html + 3: source.css.embedded.html + 4: comment.block.html punctuation.definition.comment.end.html + + style-lang-attribute: + - match: (?i:lang){{attribute_name_break}} + scope: meta.attribute-with-value.html entity.other.attribute-name.html + set: style-lang-attribute-assignment + + style-lang-attribute-assignment: + - meta_content_scope: meta.tag.style.begin.html meta.attribute-with-value.html + - match: = + scope: punctuation.separator.key-value.html + set: style-lang-attribute-value + - match: (?=\S) + set: style-css + + style-lang-attribute-value: + - meta_include_prototype: false + - meta_scope: meta.tag.style.begin.html meta.attribute-with-value.html + - include: style-lang-decider + + style-lang-decider: + - !style_language [ sass, source.sass ] + - !style_language [ scss, source.scss ] + - !style_language [ stylus, source.stylus ] + - !style_language [ postcss\?parser=sugarss, source.sss ] + - !style_language [ postcss, source.postcss ] + - !style_language [ less, source.less ] + - match: (?=\S) + set: + - style-css + - tag-generic-attribute-meta + - tag-generic-attribute-value + +###[ TEMPLATE TAG ]########################################################### + + template-tag: + - match: (<)((?i:template)){{tag_name_break}} + captures: + 1: punctuation.definition.tag.begin.html + 2: entity.name.tag.template.html + push: template-mustache + - match: (