diff --git a/plugins/textmate/lib/bundles/vue/LICENSE b/plugins/textmate/lib/bundles/vue/LICENSE
new file mode 100644
index 0000000000000..b55e47a7e8758
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021-present Johnson Chu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/plugins/textmate/lib/bundles/vue/README.md b/plugins/textmate/lib/bundles/vue/README.md
new file mode 100644
index 0000000000000..c719f17d0b584
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/README.md
@@ -0,0 +1,119 @@
+# Vue (Official)
+
+
+
+
+
+
+Vue language support extension for VSCode, providing a full development experience for Vue Single File Components (SFCs).
+
+## Features
+
+- **Syntax Highlighting** - Supports HTML, CSS, JavaScript, TypeScript, Pug, SCSS, Less, etc. in Vue SFCs
+- **Intelligent Completion** - Auto-completion for components, props, events, slots, and directives
+- **Type Checking** - Full TypeScript type inference, including expressions in templates
+- **Error Diagnostics** - Real-time display of Vue compiler errors
+- **Code Navigation** - Go to definition, find references
+- **Refactoring** - Rename, extract component
+- **Formatting** - Format SFCs by block
+
+## Installation
+
+Search for `Vue (Official)` or `Vue.volar` in the VSCode extension marketplace and click install.
+
+## Configuration
+
+### Editor Settings
+
+| Option | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| `vue.editor.focusMode` | `boolean` | `false` | Enable focus mode |
+| `vue.editor.reactivityVisualization` | `boolean` | `true` | Show reactivity variable visualization |
+| `vue.editor.templateInterpolationDecorators` | `boolean` | `true` | Show template interpolation decorators |
+
+### Completion Settings
+
+| Option | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| `vue.suggest.componentNameCasing` | `string` | `preferPascalCase` | Component name casing style (`preferKebabCase`, `preferPascalCase`, `alwaysKebabCase`, `alwaysPascalCase`) |
+| `vue.suggest.propNameCasing` | `string` | `preferCamelCase` | Prop name casing style (`preferKebabCase`, `preferCamelCase`, `alwaysKebabCase`, `alwaysCamelCase`) |
+| `vue.suggest.defineAssignment` | `boolean` | `true` | Suggest assignments for `defineProps`, etc. |
+
+### Auto-Insert Settings
+
+| Option | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| `vue.autoInsert.dotValue` | `boolean` | `false` | Auto-insert `.value` |
+| `vue.autoInsert.bracketSpacing` | `boolean` | `true` | Auto-insert spaces in `{{ }}` |
+
+### Inlay Hints Settings
+
+| Option | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| `vue.inlayHints.destructuredProps` | `boolean` | `false` | Show types for destructured props |
+| `vue.inlayHints.inlineHandlerLeading` | `boolean` | `false` | Show parameters for inline handlers |
+| `vue.inlayHints.missingProps` | `boolean` | `false` | Show missing required props |
+| `vue.inlayHints.optionsWrapper` | `boolean` | `false` | Show Options API wrapper |
+| `vue.inlayHints.vBindShorthand` | `boolean` | `false` | Show v-bind shorthand hints |
+
+### Formatting Settings
+
+| Option | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| `vue.format.script.enabled` | `boolean` | `true` | Enable script block formatting |
+| `vue.format.template.enabled` | `boolean` | `true` | Enable template block formatting |
+| `vue.format.style.enabled` | `boolean` | `true` | Enable style block formatting |
+| `vue.format.wrapAttributes` | `string` | `auto` | Attribute wrapping style |
+
+### Server Settings
+
+| Option | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| `vue.server.path` | `string` | - | Custom language server path |
+| `vue.server.includeLanguages` | `string[]` | `["vue"]` | Language IDs to process |
+| `vue.trace.server` | `string` | `off` | Server trace level |
+
+## Commands
+
+| Command | Description |
+| :--- | :--- |
+| `Vue: Welcome` | Open the welcome page |
+| `Vue: Restart Server` | Restart the language server |
+
+## Using Workspace TypeScript
+
+It is recommended to use the TypeScript version from your project instead of the one built into VSCode:
+
+1. Create `.vscode/settings.json` in your project root
+2. Add the following settings:
+
+```json
+{
+ "typescript.tsdk": "node_modules/typescript/lib",
+ "typescript.enablePromptUseWorkspaceTsdk": true
+}
+```
+
+## Troubleshooting
+
+If you encounter any issues, you can try the following steps:
+
+1. **Reload Window**: Run the `Developer: Reload Window` command in VSCode
+2. **Check `vue-tsc`**: Run `npx vue-tsc --noEmit` in the command line to check for type errors
+3. **Check Output Channel**: In VSCode's "Output" panel, select `Vue Language Server` to see if there are any error messages
+
+If the problem persists, feel free to open an issue on [GitHub Issues](https://github.com/vuejs/language-tools/issues).
+
+## ❤️ Sponsors
+
+This project's continued development is made possible by our generous sponsors:
+
+
+
+
+
+
+
+## License
+
+[MIT](https://github.com/vuejs/language-tools/blob/master/LICENSE) License
diff --git a/plugins/textmate/lib/bundles/vue/package.json b/plugins/textmate/lib/bundles/vue/package.json
new file mode 100644
index 0000000000000..3a974feca577b
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/package.json
@@ -0,0 +1,450 @@
+{
+ "name": "volar",
+ "version": "3.2.6",
+ "description": "Language Support for Vue",
+ "license": null,
+ "contributes": {
+ "jsonValidation": [
+ {
+ "fileMatch": [
+ "tsconfig.json",
+ "tsconfig.*.json",
+ "tsconfig-*.json",
+ "jsconfig.json",
+ "jsconfig.*.json",
+ "jsconfig-*.json"
+ ],
+ "url": "./schemas/vue-tsconfig.schema.json"
+ }
+ ],
+ "languages": [
+ {
+ "id": "vue",
+ "extensions": [
+ ".vue"
+ ],
+ "configuration": "./languages/vue-language-configuration.json"
+ },
+ {
+ "id": "markdown",
+ "configuration": "./languages/markdown-language-configuration.json"
+ },
+ {
+ "id": "html",
+ "configuration": "./languages/sfc-template-language-configuration.json"
+ },
+ {
+ "id": "jade",
+ "configuration": "./languages/sfc-template-language-configuration.json"
+ }
+ ],
+ "grammars": [
+ {
+ "language": "vue",
+ "scopeName": "text.html.vue",
+ "path": "./syntaxes/vue.tmLanguage.json",
+ "embeddedLanguages": {
+ "text.html.vue": "vue",
+ "text": "plaintext",
+ "text.html.derivative": "html",
+ "text.html.markdown": "markdown",
+ "text.pug": "jade",
+ "source.css": "css",
+ "source.css.scss": "scss",
+ "source.css.less": "less",
+ "source.sass": "sass",
+ "source.stylus": "stylus",
+ "source.postcss": "postcss",
+ "source.js": "javascript",
+ "source.ts": "typescript",
+ "source.js.jsx": "javascriptreact",
+ "source.tsx": "typescriptreact",
+ "source.coffee": "coffeescript",
+ "meta.tag.js": "jsx-tags",
+ "meta.tag.tsx": "jsx-tags",
+ "meta.tag.without-attributes.js": "jsx-tags",
+ "meta.tag.without-attributes.tsx": "jsx-tags",
+ "source.json": "json",
+ "source.json.comments": "jsonc",
+ "source.json5": "json5",
+ "source.yaml": "yaml",
+ "source.toml": "toml",
+ "source.graphql": "graphql"
+ },
+ "unbalancedBracketScopes": [
+ "keyword.operator.relational",
+ "storage.type.function.arrow",
+ "keyword.operator.bitwise.shift",
+ "meta.brace.angle",
+ "punctuation.definition.tag"
+ ]
+ },
+ {
+ "scopeName": "markdown.vue.codeblock",
+ "path": "./syntaxes/markdown-vue.json",
+ "injectTo": [
+ "text.html.markdown"
+ ],
+ "embeddedLanguages": {
+ "meta.embedded.block.vue": "vue",
+ "text.html.vue": "vue",
+ "text": "plaintext",
+ "text.html.derivative": "html",
+ "text.html.markdown": "markdown",
+ "text.pug": "jade",
+ "source.css": "css",
+ "source.css.scss": "scss",
+ "source.css.less": "less",
+ "source.sass": "sass",
+ "source.stylus": "stylus",
+ "source.postcss": "postcss",
+ "source.js": "javascript",
+ "source.ts": "typescript",
+ "source.js.jsx": "javascriptreact",
+ "source.tsx": "typescriptreact",
+ "source.coffee": "coffeescript",
+ "meta.tag.js": "jsx-tags",
+ "meta.tag.tsx": "jsx-tags",
+ "meta.tag.without-attributes.js": "jsx-tags",
+ "meta.tag.without-attributes.tsx": "jsx-tags",
+ "source.json": "json",
+ "source.json.comments": "jsonc",
+ "source.json5": "json5",
+ "source.yaml": "yaml",
+ "source.toml": "toml",
+ "source.graphql": "graphql"
+ }
+ },
+ {
+ "scopeName": "mdx.vue.codeblock",
+ "path": "./syntaxes/mdx-vue.json",
+ "injectTo": [
+ "source.mdx"
+ ],
+ "embeddedLanguages": {
+ "mdx.embedded.vue": "vue",
+ "text.html.vue": "vue",
+ "text": "plaintext",
+ "text.html.derivative": "html",
+ "text.html.markdown": "markdown",
+ "text.pug": "jade",
+ "source.css": "css",
+ "source.css.scss": "scss",
+ "source.css.less": "less",
+ "source.sass": "sass",
+ "source.stylus": "stylus",
+ "source.postcss": "postcss",
+ "source.js": "javascript",
+ "source.ts": "typescript",
+ "source.js.jsx": "javascriptreact",
+ "source.tsx": "typescriptreact",
+ "source.coffee": "coffeescript",
+ "meta.tag.js": "jsx-tags",
+ "meta.tag.tsx": "jsx-tags",
+ "meta.tag.without-attributes.js": "jsx-tags",
+ "meta.tag.without-attributes.tsx": "jsx-tags",
+ "source.json": "json",
+ "source.json.comments": "jsonc",
+ "source.json5": "json5",
+ "source.yaml": "yaml",
+ "source.toml": "toml",
+ "source.graphql": "graphql"
+ }
+ },
+ {
+ "scopeName": "vue.directives",
+ "path": "./syntaxes/vue-directives.json",
+ "injectTo": [
+ "text.html.vue",
+ "text.html.markdown",
+ "text.html.derivative",
+ "text.pug"
+ ]
+ },
+ {
+ "scopeName": "vue.interpolations",
+ "path": "./syntaxes/vue-interpolations.json",
+ "injectTo": [
+ "text.html.vue",
+ "text.html.markdown",
+ "text.html.derivative",
+ "text.pug"
+ ]
+ },
+ {
+ "scopeName": "vue.sfc.script.leading-operator-fix",
+ "path": "./syntaxes/vue-sfc-script-leading-operator-fix.json",
+ "injectTo": [
+ "text.html.vue"
+ ]
+ },
+ {
+ "scopeName": "vue.sfc.style.variable.injection",
+ "path": "./syntaxes/vue-sfc-style-variable-injection.json",
+ "injectTo": [
+ "text.html.vue"
+ ]
+ }
+ ],
+ "semanticTokenScopes": [
+ {
+ "language": "vue",
+ "scopes": {
+ "component": [
+ "support.class.component.vue",
+ "entity.name.type.class.vue"
+ ]
+ }
+ },
+ {
+ "language": "markdown",
+ "scopes": {
+ "component": [
+ "support.class.component.vue",
+ "entity.name.type.class.vue"
+ ]
+ }
+ },
+ {
+ "language": "html",
+ "scopes": {
+ "component": [
+ "support.class.component.vue",
+ "entity.name.type.class.vue"
+ ]
+ }
+ }
+ ],
+ "breakpoints": [
+ {
+ "language": "vue"
+ }
+ ],
+ "configuration": {
+ "type": "object",
+ "title": "Vue",
+ "properties": {
+ "vue.trace.server": {
+ "scope": "window",
+ "type": "string",
+ "enum": [
+ "off",
+ "messages",
+ "verbose"
+ ],
+ "default": "off",
+ "markdownDescription": "%configuration.trace.server%"
+ },
+ "vue.editor.focusMode": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.editor.focusMode%"
+ },
+ "vue.editor.reactivityVisualization": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.editor.reactivityVisualization%"
+ },
+ "vue.editor.templateInterpolationDecorators": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.editor.templateInterpolationDecorators%"
+ },
+ "vue.server.path": {
+ "type": "string",
+ "markdownDescription": "%configuration.server.path%"
+ },
+ "vue.server.includeLanguages": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [
+ "vue"
+ ],
+ "markdownDescription": "%configuration.server.includeLanguages%"
+ },
+ "vue.codeActions.askNewComponentName": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.codeActions.askNewComponentName%"
+ },
+ "vue.hover.rich": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.hover.rich%"
+ },
+ "vue.suggest.componentNameCasing": {
+ "type": "string",
+ "enum": [
+ "preferKebabCase",
+ "preferPascalCase",
+ "alwaysKebabCase",
+ "alwaysPascalCase"
+ ],
+ "enumDescriptions": [
+ "Prefer kebab-case (lowercase with hyphens, e.g. my-component)",
+ "Prefer PascalCase (UpperCamelCase, e.g. MyComponent)",
+ "Always kebab-case (enforce kebab-case, e.g. my-component)",
+ "Always PascalCase (enforce PascalCase, e.g. MyComponent)"
+ ],
+ "default": "preferPascalCase",
+ "markdownDescription": "%configuration.suggest.componentNameCasing%"
+ },
+ "vue.suggest.propNameCasing": {
+ "type": "string",
+ "enum": [
+ "preferKebabCase",
+ "preferCamelCase",
+ "alwaysKebabCase",
+ "alwaysCamelCase"
+ ],
+ "enumDescriptions": [
+ "Prefer kebab-case (lowercase with hyphens, e.g. my-prop)",
+ "Prefer camelCase (lowerCamelCase, e.g. myProp)",
+ "Always kebab-case (enforce kebab-case, e.g. my-prop)",
+ "Always camelCase (enforce camelCase, e.g. myProp)"
+ ],
+ "default": "preferKebabCase",
+ "markdownDescription": "%configuration.suggest.propNameCasing%"
+ },
+ "vue.suggest.defineAssignment": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.suggest.defineAssignment%"
+ },
+ "vue.autoInsert.dotValue": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.autoInsert.dotValue%"
+ },
+ "vue.autoInsert.bracketSpacing": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.autoInsert.bracketSpacing%"
+ },
+ "vue.inlayHints.destructuredProps": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.inlayHints.destructuredProps%"
+ },
+ "vue.inlayHints.missingProps": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.inlayHints.missingProps%"
+ },
+ "vue.inlayHints.inlineHandlerLeading": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.inlayHints.inlineHandlerLeading%"
+ },
+ "vue.inlayHints.optionsWrapper": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.inlayHints.optionsWrapper%"
+ },
+ "vue.inlayHints.vBindShorthand": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.inlayHints.vBindShorthand%"
+ },
+ "vue.format.template.initialIndent": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.format.template.initialIndent%"
+ },
+ "vue.format.script.initialIndent": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.format.script.initialIndent%"
+ },
+ "vue.format.style.initialIndent": {
+ "type": "boolean",
+ "default": false,
+ "markdownDescription": "%configuration.format.style.initialIndent%"
+ },
+ "vue.format.script.enabled": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.format.script.enabled%"
+ },
+ "vue.format.template.enabled": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.format.template.enabled%"
+ },
+ "vue.format.style.enabled": {
+ "type": "boolean",
+ "default": true,
+ "markdownDescription": "%configuration.format.style.enabled%"
+ },
+ "vue.format.wrapAttributes": {
+ "type": "string",
+ "default": "auto",
+ "enum": [
+ "auto",
+ "force",
+ "force-aligned",
+ "force-expand-multiline",
+ "aligned-multiple",
+ "preserve",
+ "preserve-aligned"
+ ],
+ "markdownDescription": "%configuration.format.wrapAttributes%"
+ }
+ }
+ },
+ "commands": [
+ {
+ "command": "vue.welcome",
+ "title": "%command.welcome%",
+ "category": "Vue"
+ },
+ {
+ "command": "vue.action.restartServer",
+ "title": "%command.action.restartServer%",
+ "category": "Vue"
+ }
+ ],
+ "menus": {
+ "editor/context": [
+ {
+ "command": "typescript.goToSourceDefinition",
+ "when": "tsSupportsSourceDefinition && resourceLangId == vue",
+ "group": "navigation@9"
+ }
+ ],
+ "explorer/context": [
+ {
+ "command": "typescript.findAllFileReferences",
+ "when": "tsSupportsFileReferences && resourceLangId == vue",
+ "group": "4_search"
+ }
+ ],
+ "editor/title/context": [
+ {
+ "command": "typescript.findAllFileReferences",
+ "when": "tsSupportsFileReferences && resourceLangId == vue"
+ }
+ ],
+ "commandPalette": [
+ {
+ "command": "typescript.reloadProjects",
+ "when": "editorLangId == vue && typescript.isManagedFile"
+ },
+ {
+ "command": "typescript.goToProjectConfig",
+ "when": "editorLangId == vue && typescript.isManagedFile"
+ },
+ {
+ "command": "typescript.sortImports",
+ "when": "supportedCodeAction =~ /(\\s|^)source\\.sortImports\\b/ && editorLangId =~ /^vue$/"
+ },
+ {
+ "command": "typescript.removeUnusedImports",
+ "when": "supportedCodeAction =~ /(\\s|^)source\\.removeUnusedImports\\b/ && editorLangId =~ /^vue$/"
+ }
+ ]
+ }
+ }
+}
diff --git a/plugins/textmate/lib/bundles/vue/syntaxes/markdown-vue.json b/plugins/textmate/lib/bundles/vue/syntaxes/markdown-vue.json
new file mode 100644
index 0000000000000..da6b81b0a06d7
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/syntaxes/markdown-vue.json
@@ -0,0 +1,40 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "fileTypes": [],
+ "injectionSelector": "L:text.html.markdown",
+ "patterns": [
+ {
+ "include": "#vue-code-block"
+ }
+ ],
+ "repository": {
+ "vue-code-block": {
+ "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(vue)((\\s+|:|,|\\{|\\?)[^`~]*)?$)",
+ "name": "markup.fenced_code.block.markdown",
+ "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
+ "beginCaptures": {
+ "3": {
+ "name": "punctuation.definition.markdown"
+ },
+ "4": {
+ "name": "fenced_code.block.language.markdown"
+ },
+ "5": {
+ "name": "fenced_code.block.language.attributes.markdown",
+ "patterns": []
+ }
+ },
+ "endCaptures": {
+ "3": {
+ "name": "punctuation.definition.markdown"
+ }
+ },
+ "patterns": [
+ {
+ "include": "text.html.vue"
+ }
+ ]
+ }
+ },
+ "scopeName": "markdown.vue.codeblock"
+}
diff --git a/plugins/textmate/lib/bundles/vue/syntaxes/mdx-vue.json b/plugins/textmate/lib/bundles/vue/syntaxes/mdx-vue.json
new file mode 100644
index 0000000000000..30516c895517f
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/syntaxes/mdx-vue.json
@@ -0,0 +1,64 @@
+{
+ "fileTypes": [],
+ "scopeName": "mdx.vue.codeblock",
+ "injectionSelector": "L:source.mdx",
+ "patterns": [
+ {
+ "include": "#vue-code-block"
+ }
+ ],
+ "repository": {
+ "vue-code-block": {
+ "patterns": [
+ {
+ "begin": "(?:^|\\G)[\\t ]*(`{3,})(?:[\\t ]*((?i:(?:.*\\.)?vue))(?:[\\t ]+((?:[^\\n\\r`])+))?)(?:[\\t ]*$)",
+ "beginCaptures": {
+ "1": {
+ "name": "string.other.begin.code.fenced.mdx"
+ },
+ "2": {
+ "name": "entity.name.function.mdx"
+ }
+ },
+ "contentName": "meta.embedded.vue",
+ "end": "(\\1)(?:[\\t ]*$)",
+ "endCaptures": {
+ "1": {
+ "name": "string.other.end.code.fenced.mdx"
+ }
+ },
+ "name": "markup.code.vue.mdx",
+ "patterns": [
+ {
+ "include": "text.html.vue"
+ }
+ ]
+ },
+ {
+ "begin": "(?:^|\\G)[\\t ]*(~{3,})(?:[\\t ]*((?i:(?:.*\\.)?vue))(?:[\\t ]+((?:[^\\n\\r])+))?)(?:[\\t ]*$)",
+ "beginCaptures": {
+ "1": {
+ "name": "string.other.begin.code.fenced.mdx"
+ },
+ "2": {
+ "name": "entity.name.function.mdx"
+ }
+ },
+ "contentName": "meta.embedded.vue",
+ "end": "(\\1)(?:[\\t ]*$)",
+ "endCaptures": {
+ "1": {
+ "name": "string.other.end.code.fenced.mdx"
+ }
+ },
+ "name": "markup.code.vue.mdx",
+ "patterns": [
+ {
+ "include": "text.html.vue"
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/plugins/textmate/lib/bundles/vue/syntaxes/vue-directives.json b/plugins/textmate/lib/bundles/vue/syntaxes/vue-directives.json
new file mode 100644
index 0000000000000..0ebf50521227f
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/syntaxes/vue-directives.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "fileTypes": [],
+ "injectionSelector": "L:meta.tag -meta.attribute -meta.ng-binding -entity.name.tag.pug -attribute_value -source.tsx -source.js.jsx, L:meta.element -meta.attribute",
+ "patterns": [
+ {
+ "include": "text.html.vue#vue-directives"
+ }
+ ],
+ "scopeName": "vue.directives"
+}
diff --git a/plugins/textmate/lib/bundles/vue/syntaxes/vue-interpolations.json b/plugins/textmate/lib/bundles/vue/syntaxes/vue-interpolations.json
new file mode 100644
index 0000000000000..f76480889b000
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/syntaxes/vue-interpolations.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "fileTypes": [],
+ "injectionSelector": "L:text.pug -comment -string.comment, L:text.html.derivative -comment.block, L:text.html.markdown -comment.block",
+ "patterns": [
+ {
+ "include": "text.html.vue#vue-interpolations"
+ }
+ ],
+ "scopeName": "vue.interpolations"
+}
diff --git a/plugins/textmate/lib/bundles/vue/syntaxes/vue-sfc-script-leading-operator-fix.json b/plugins/textmate/lib/bundles/vue/syntaxes/vue-sfc-script-leading-operator-fix.json
new file mode 100644
index 0000000000000..38693d1f122c9
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/syntaxes/vue-sfc-script-leading-operator-fix.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "fileTypes": [],
+ "injectionSelector": "L:text.html.vue source.js, L:text.html.vue source.js.jsx, L:text.html.vue source.tsx",
+ "patterns": [
+ {
+ "match": "^\\s*(<)(?=\\s+[_$[:alpha:]])",
+ "captures": {
+ "1": {
+ "name": "keyword.operator.relational.js"
+ }
+ }
+ }
+ ],
+ "scopeName": "vue.sfc.script.leading-operator-fix"
+}
diff --git a/plugins/textmate/lib/bundles/vue/syntaxes/vue-sfc-style-variable-injection.json b/plugins/textmate/lib/bundles/vue/syntaxes/vue-sfc-style-variable-injection.json
new file mode 100644
index 0000000000000..d566d0add31b3
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/syntaxes/vue-sfc-style-variable-injection.json
@@ -0,0 +1,48 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "fileTypes": [],
+ "injectionSelector": "L:source.css -comment, L:source.postcss -comment, L:source.sass -comment, L:source.stylus -comment",
+ "patterns": [
+ {
+ "include": "#vue-sfc-style-variable-injection"
+ }
+ ],
+ "repository": {
+ "vue-sfc-style-variable-injection": {
+ "begin": "\\b(v-bind)\\s*\\(",
+ "name": "vue.sfc.style.variable.injection.v-bind",
+ "end": "\\)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.function"
+ }
+ },
+ "patterns": [
+ {
+ "begin": "('|\")",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html"
+ }
+ },
+ "end": "(\\1)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html"
+ }
+ },
+ "name": "source.ts.embedded.html.vue",
+ "patterns": [
+ {
+ "include": "source.js"
+ }
+ ]
+ },
+ {
+ "include": "source.js"
+ }
+ ]
+ }
+ },
+ "scopeName": "vue.sfc.style.variable.injection"
+}
diff --git a/plugins/textmate/lib/bundles/vue/syntaxes/vue.tmLanguage.json b/plugins/textmate/lib/bundles/vue/syntaxes/vue.tmLanguage.json
new file mode 100644
index 0000000000000..81fdecc982bdf
--- /dev/null
+++ b/plugins/textmate/lib/bundles/vue/syntaxes/vue.tmLanguage.json
@@ -0,0 +1,1555 @@
+{
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+ "name": "Vue",
+ "scopeName": "text.html.vue",
+ "patterns": [
+ {
+ "include": "#vue-comments"
+ },
+ {
+ "include": "#self-closing-tag"
+ },
+ {
+ "begin": "(<)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ }
+ },
+ "end": "(>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)md\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "text.html.markdown",
+ "patterns": [
+ {
+ "include": "text.html.markdown"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?!template(?![A-Za-z0-9:-]))([A-Za-z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)html\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "contentName": "text.html.derivative",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "include": "#html-stuff"
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)pug\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "text.pug",
+ "patterns": [
+ {
+ "include": "text.pug"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)stylus\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.stylus",
+ "patterns": [
+ {
+ "include": "source.stylus"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)postcss\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.postcss",
+ "patterns": [
+ {
+ "include": "source.postcss"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)sass\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.sass",
+ "patterns": [
+ {
+ "include": "source.sass"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)css\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.css",
+ "patterns": [
+ {
+ "include": "source.css"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)scss\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.css.scss",
+ "patterns": [
+ {
+ "include": "source.css.scss"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)less\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.css.less",
+ "patterns": [
+ {
+ "include": "source.css.less"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)js\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.js",
+ "patterns": [
+ {
+ "include": "source.js"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)ts\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)(?=[^\\n]*<\\/script[\\s>])",
+ "end": "(?=<\\/script[\\s>])",
+ "name": "source.ts",
+ "patterns": [
+ {
+ "include": "source.ts"
+ }
+ ]
+ },
+ {
+ "begin": "(?<=>)",
+ "while": "^(?!\\s*<\\/script[\\s>])",
+ "name": "source.ts",
+ "patterns": [
+ {
+ "include": "source.ts"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)jsx\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.js.jsx",
+ "patterns": [
+ {
+ "include": "source.js.jsx"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)tsx\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)(?=[^\\n]*<\\/script[\\s>])",
+ "end": "(?=<\\/script[\\s>])",
+ "name": "source.tsx",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ]
+ },
+ {
+ "begin": "(?<=>)",
+ "while": "^(?!\\s*<\\/script[\\s>])",
+ "name": "source.tsx",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)coffee\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.coffee",
+ "patterns": [
+ {
+ "include": "source.coffee"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)json\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.json",
+ "patterns": [
+ {
+ "include": "source.json"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)jsonc\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.json.comments",
+ "patterns": [
+ {
+ "include": "source.json.comments"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)json5\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.json5",
+ "patterns": [
+ {
+ "include": "source.json5"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)yaml\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.yaml",
+ "patterns": [
+ {
+ "include": "source.yaml"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)toml\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.toml",
+ "patterns": [
+ {
+ "include": "source.toml"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)(gql|graphql)\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "source.graphql",
+ "patterns": [
+ {
+ "include": "source.graphql"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)vue\\b\\2)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "text.html.vue",
+ "patterns": [
+ {
+ "include": "text.html.vue"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(template)(?=\\s|\\/?>)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/template[\\s>])",
+ "name": "text.html.derivative",
+ "patterns": [
+ {
+ "include": "#html-stuff"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(script)(?=\\s|\\/?>)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#multi-line-script-tag-stuff"
+ }
+ ]
+ },
+ {
+ "begin": "(style)(?=\\s|\\/?>)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#multi-line-style-tag-stuff"
+ }
+ ]
+ },
+ {
+ "begin": "([a-zA-Z0-9:-]+)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.name.tag.$1.html.vue"
+ }
+ },
+ "end": "()(\\1)\\s*(?=>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/)",
+ "name": "text"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "repository": {
+ "multi-line-script-tag-stuff": {
+ "begin": "\\G",
+ "end": "(?=<\\/script[\\s>])",
+ "patterns": [
+ {
+ "begin": "\\G(?!\\blang\\s*=\\s*(?:['\"]?)(?:ts|tsx|jsx|coffee)\\b)",
+ "end": "(?=\\blang\\s*=\\s*(?:['\"]?)(?:ts|tsx|jsx|coffee)\\b)|(>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "name": "meta.tag-stuff",
+ "patterns": [
+ {
+ "include": "#vue-directives"
+ },
+ {
+ "include": "text.html.basic#attribute"
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)ts\\b)",
+ "end": "(?=<\\/script[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)(?=[^\\n]*<\\/script[\\s>])",
+ "end": "(?=<\\/script[\\s>])",
+ "name": "source.ts",
+ "patterns": [
+ {
+ "include": "source.ts"
+ }
+ ]
+ },
+ {
+ "begin": "(?<=>)",
+ "while": "^(?!\\s*<\\/script[\\s>])",
+ "name": "source.ts",
+ "patterns": [
+ {
+ "include": "source.ts"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)tsx\\b)",
+ "end": "(?=<\\/script[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)(?=[^\\n]*<\\/script[\\s>])",
+ "end": "(?=<\\/script[\\s>])",
+ "name": "source.tsx",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ]
+ },
+ {
+ "begin": "(?<=>)",
+ "while": "^(?!\\s*<\\/script[\\s>])",
+ "name": "source.tsx",
+ "patterns": [
+ {
+ "include": "source.tsx"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)jsx\\b)",
+ "end": "(?=<\\/script[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/script[\\s>])",
+ "name": "source.js.jsx",
+ "patterns": [
+ {
+ "include": "source.js.jsx"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)coffee\\b)",
+ "end": "(?=<\\/script[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/script[\\s>])",
+ "name": "source.coffee",
+ "patterns": [
+ {
+ "include": "source.coffee"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/script[\\s>])",
+ "name": "source.js",
+ "patterns": [
+ {
+ "include": "source.js"
+ }
+ ]
+ }
+ ]
+ },
+ "multi-line-style-tag-stuff": {
+ "begin": "\\G",
+ "end": "(?=<\\/style[\\s>])",
+ "patterns": [
+ {
+ "begin": "\\G(?!\\blang\\s*=\\s*(?:['\"]?)(?:scss|stylus|less|postcss)\\b)",
+ "end": "(?=\\blang\\s*=\\s*(?:['\"]?)(?:scss|stylus|less|postcss)\\b)|(>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "name": "meta.tag-stuff",
+ "patterns": [
+ {
+ "include": "#vue-directives"
+ },
+ {
+ "include": "text.html.basic#attribute"
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)scss\\b)",
+ "end": "(?=<\\/style[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/style[\\s>])",
+ "name": "source.css.scss",
+ "patterns": [
+ {
+ "include": "source.css.scss"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)stylus\\b)",
+ "end": "(?=<\\/style[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/style[\\s>])",
+ "name": "source.stylus",
+ "patterns": [
+ {
+ "include": "source.stylus"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)less\\b)",
+ "end": "(?=<\\/style[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/style[\\s>])",
+ "name": "source.css.less",
+ "patterns": [
+ {
+ "include": "source.css.less"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?=\\blang\\s*=\\s*(?:['\"]?)postcss\\b)",
+ "end": "(?=<\\/style[\\s>])",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/style[\\s>])",
+ "name": "source.postcss",
+ "patterns": [
+ {
+ "include": "source.postcss"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(?<=>)",
+ "end": "(?=<\\/style[\\s>])",
+ "name": "source.css",
+ "patterns": [
+ {
+ "include": "source.css"
+ }
+ ]
+ }
+ ]
+ },
+ "self-closing-tag": {
+ "begin": "(<)([a-zA-Z0-9:-]+)(?=([^>]+/>))",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "end": "(/>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "name": "self-closing-tag",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ }
+ ]
+ },
+ "template-tag": {
+ "patterns": [
+ {
+ "include": "#template-tag-1"
+ },
+ {
+ "include": "#template-tag-2"
+ }
+ ]
+ },
+ "template-tag-1": {
+ "begin": "(<)(template)\\b(>)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ },
+ "3": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "end": "(/?>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "name": "meta.template-tag.start",
+ "patterns": [
+ {
+ "begin": "\\G",
+ "end": "(?=/>)|(()(template)(?=[\\s>]))",
+ "endCaptures": {
+ "2": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "3": {
+ "name": "entity.name.tag.$3.html.vue"
+ }
+ },
+ "name": "meta.template-tag.end",
+ "patterns": [
+ {
+ "include": "#html-stuff"
+ }
+ ]
+ }
+ ]
+ },
+ "template-tag-2": {
+ "begin": "(<)(template)(?=\\s|\\/?>)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "2": {
+ "name": "entity.name.tag.$2.html.vue"
+ }
+ },
+ "end": "(/?>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "name": "meta.template-tag.start",
+ "patterns": [
+ {
+ "begin": "\\G",
+ "end": "(?=/>)|(()(template)(?=[\\s>]))",
+ "endCaptures": {
+ "2": {
+ "name": "punctuation.definition.tag.begin.html.vue"
+ },
+ "3": {
+ "name": "entity.name.tag.$3.html.vue"
+ }
+ },
+ "name": "meta.template-tag.end",
+ "patterns": [
+ {
+ "include": "#tag-stuff"
+ },
+ {
+ "include": "#html-stuff"
+ }
+ ]
+ }
+ ]
+ },
+ "html-stuff": {
+ "patterns": [
+ {
+ "include": "#template-tag"
+ },
+ {
+ "include": "text.html.derivative"
+ },
+ {
+ "include": "text.html.basic"
+ }
+ ]
+ },
+ "tag-stuff": {
+ "begin": "\\G",
+ "end": "(?=/>)|(>)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.tag.end.html.vue"
+ }
+ },
+ "name": "meta.tag-stuff",
+ "patterns": [
+ {
+ "include": "#vue-directives"
+ },
+ {
+ "include": "text.html.basic#attribute"
+ }
+ ]
+ },
+ "vue-directives": {
+ "patterns": [
+ {
+ "include": "#vue-directives-control"
+ },
+ {
+ "include": "#vue-directives-generic-attr"
+ },
+ {
+ "include": "#vue-directives-style-attr"
+ },
+ {
+ "include": "#vue-directives-original"
+ }
+ ]
+ },
+ "vue-directives-original": {
+ "begin": "(?:(?:(v-[\\w-]+)(:)?)|([:\\.])|(@)|(#))(?:(?:(\\[)([^\\]]*)(\\]))|([\\w-]+))?",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.other.attribute-name.html.vue"
+ },
+ "2": {
+ "name": "punctuation.separator.key-value.html.vue"
+ },
+ "3": {
+ "name": "punctuation.attribute-shorthand.bind.html.vue"
+ },
+ "4": {
+ "name": "punctuation.attribute-shorthand.event.html.vue"
+ },
+ "5": {
+ "name": "punctuation.attribute-shorthand.slot.html.vue"
+ },
+ "6": {
+ "name": "punctuation.separator.key-value.html.vue"
+ },
+ "7": {
+ "name": "source.ts.embedded.html.vue",
+ "patterns": [
+ {
+ "include": "source.ts#expression"
+ }
+ ]
+ },
+ "8": {
+ "name": "punctuation.separator.key-value.html.vue"
+ },
+ "9": {
+ "name": "entity.other.attribute-name.html.vue"
+ }
+ },
+ "end": "(?=\\s*[^=\\s])",
+ "name": "meta.attribute.directive.vue",
+ "patterns": [
+ {
+ "match": "(\\.)([\\w-]*)",
+ "1": {
+ "name": "punctuation.separator.key-value.html.vue"
+ },
+ "2": {
+ "name": "entity.other.attribute-name.html.vue"
+ }
+ },
+ {
+ "include": "#vue-directives-expression"
+ }
+ ]
+ },
+ "vue-directives-control": {
+ "begin": "(?:(v-for)|(v-if|v-else-if|v-else))(?=[=/>)\\s])",
+ "beginCaptures": {
+ "1": {
+ "name": "keyword.control.loop.vue"
+ },
+ "2": {
+ "name": "keyword.control.conditional.vue"
+ }
+ },
+ "end": "(?=\\s*[^=\\s])",
+ "name": "meta.attribute.directive.control.vue",
+ "patterns": [
+ {
+ "include": "#vue-directives-expression"
+ }
+ ]
+ },
+ "vue-directives-expression": {
+ "patterns": [
+ {
+ "begin": "(=)\\s*('|\"|`)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.separator.key-value.html.vue"
+ },
+ "2": {
+ "name": "punctuation.definition.string.begin.html.vue"
+ }
+ },
+ "end": "(\\2)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.string.end.html.vue"
+ }
+ },
+ "patterns": [
+ {
+ "begin": "(?<=('|\"|`))",
+ "end": "(?=\\1)",
+ "name": "source.ts.embedded.html.vue",
+ "patterns": [
+ {
+ "include": "source.ts#expression"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "begin": "(=)\\s*(?=[^'\"`])",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.separator.key-value.html.vue"
+ }
+ },
+ "end": "(?=(\\s|>|\\/>))",
+ "patterns": [
+ {
+ "begin": "(?=[^'\"`])",
+ "end": "(?=(\\s|>|\\/>))",
+ "name": "source.ts.embedded.html.vue",
+ "patterns": [
+ {
+ "include": "source.ts#expression"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "vue-directives-style-attr": {
+ "begin": "\\b(style)\\s*(=)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.other.attribute-name.html.vue"
+ },
+ "2": {
+ "name": "punctuation.separator.key-value.html.vue"
+ }
+ },
+ "end": "(?<='|\")",
+ "name": "meta.attribute.style.vue",
+ "patterns": [
+ {
+ "comment": "Copy from source.css#rule-list-innards",
+ "begin": "('|\")",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.string.begin.html.vue"
+ }
+ },
+ "end": "(\\1)",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.string.end.html.vue"
+ }
+ },
+ "name": "source.css.embedded.html.vue",
+ "patterns": [
+ {
+ "include": "source.css#comment-block"
+ },
+ {
+ "include": "source.css#escapes"
+ },
+ {
+ "include": "source.css#font-features"
+ },
+ {
+ "match": "(?x) (?)"
+ }
+ ]
+ }
+ ]
+ },
+ "vue-interpolations": {
+ "patterns": [
+ {
+ "begin": "(\\{\\{)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.interpolation.begin.html.vue"
+ }
+ },
+ "end": "(\\}\\})",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.interpolation.end.html.vue"
+ }
+ },
+ "name": "expression.embedded.vue",
+ "patterns": [
+ {
+ "begin": "\\G",
+ "end": "(?=\\}\\})",
+ "name": "source.ts.embedded.html.vue",
+ "patterns": [
+ {
+ "include": "source.ts#expression"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "vue-comments": {
+ "patterns": [
+ {
+ "include": "#vue-comments-key-value"
+ },
+ {
+ "begin": "",
+ "name": "comment.block.vue"
+ }
+ ]
+ },
+ "vue-comments-key-value": {
+ "begin": "()",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.comment.vue"
+ }
+ },
+ "name": "comment.block.vue",
+ "patterns": [
+ {
+ "include": "source.json#value"
+ }
+ ]
+ }
+ }
+}
diff --git a/plugins/textmate/loadVSCBundles.sh b/plugins/textmate/loadVSCBundles.sh
index 5d232a8584766..02f5cfbac0624 100755
--- a/plugins/textmate/loadVSCBundles.sh
+++ b/plugins/textmate/loadVSCBundles.sh
@@ -146,6 +146,19 @@ cp -r "syntaxes" "$ROOT/lib/bundles/cmake"
cd ..
+# vue
+git clone https://github.com/vuejs/language-tools
+pushd language-tools/extensions/vscode
+
+echo "adding vue"
+mkdir -p "$ROOT/lib/bundles/vue"
+cp -r "LICENSE" "$ROOT/lib/bundles/vue"
+cp -r "package.json" "$ROOT/lib/bundles/vue"
+cp -r "README.md" "$ROOT/lib/bundles/vue"
+cp -r "syntaxes" "$ROOT/lib/bundles/vue"
+
+popd
+
mkdir -p "$ROOT/lib/bundles/terraform/syntaxes"
wget -q https://raw.githubusercontent.com/hashicorp/syntax/main/syntaxes/terraform.tmGrammar.json -O "$ROOT/lib/bundles/terraform/syntaxes/terraform.tmGrammar.json"
wget -q https://raw.githubusercontent.com/hashicorp/syntax/main/syntaxes/hcl.tmGrammar.json -O "$ROOT/lib/bundles/terraform/syntaxes/hcl.tmGrammar.json"