From eb4a6dcc24d36b676831b9980ed0e5256f71fbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Paku=C5=82a?= Date: Wed, 7 Jun 2023 13:48:10 +0200 Subject: [PATCH] Vue Support - #83 --- .../wildwebdeveloper/tests/TestVue.java | 159 +++ .../testProjects/vue-app/.gitignore | 23 + .../testProjects/vue-app/babel.config.js | 5 + .../testProjects/vue-app/jsconfig.json | 19 + .../testProjects/vue-app/package.json | 43 + .../testProjects/vue-app/public/index.html | 16 + .../testProjects/vue-app/src/App.vue | 36 + .../vue-app/src/components/HelloWorld.vue | 29 + .../src/components/HelloWorldCorrect.vue | 29 + .../testProjects/vue-app/src/main.js | 4 + .../testProjects/vue-app/vue.config.js | 4 + .../grammars/vue/Readme.md | 1 + .../grammars/vue/markdown-vue.json | 39 + .../grammars/vue/vue-directives.json | 11 + .../grammars/vue/vue-interpolations.json | 11 + .../vue/vue-sfc-style-variable-injection.json | 48 + .../grammars/vue/vue.tmLanguage.json | 1237 +++++++++++++++++ .../language-configurations/vue/Readme.md | 1 + .../vue/markdown-language-configuration.json | 56 + .../sfc-template-language-configuration.json | 8 + .../vue/vue-language-configuration.json | 145 ++ org.eclipse.wildwebdeveloper/package.json | 3 +- org.eclipse.wildwebdeveloper/plugin.xml | 58 + .../wildwebdeveloper/vue/VueClientImpl.java | 40 + .../vue/VueLanguageServer.java | 73 + .../vue/VueLanguageServerExtention.java | 29 + 26 files changed, 2126 insertions(+), 1 deletion(-) create mode 100644 org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestVue.java create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/.gitignore create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/babel.config.js create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/jsconfig.json create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/package.json create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/public/index.html create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/App.vue create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorld.vue create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorldCorrect.vue create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/main.js create mode 100644 org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/vue.config.js create mode 100644 org.eclipse.wildwebdeveloper/grammars/vue/Readme.md create mode 100644 org.eclipse.wildwebdeveloper/grammars/vue/markdown-vue.json create mode 100644 org.eclipse.wildwebdeveloper/grammars/vue/vue-directives.json create mode 100644 org.eclipse.wildwebdeveloper/grammars/vue/vue-interpolations.json create mode 100644 org.eclipse.wildwebdeveloper/grammars/vue/vue-sfc-style-variable-injection.json create mode 100644 org.eclipse.wildwebdeveloper/grammars/vue/vue.tmLanguage.json create mode 100644 org.eclipse.wildwebdeveloper/language-configurations/vue/Readme.md create mode 100644 org.eclipse.wildwebdeveloper/language-configurations/vue/markdown-language-configuration.json create mode 100644 org.eclipse.wildwebdeveloper/language-configurations/vue/sfc-template-language-configuration.json create mode 100644 org.eclipse.wildwebdeveloper/language-configurations/vue/vue-language-configuration.json create mode 100644 org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueClientImpl.java create mode 100644 org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java create mode 100644 org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java diff --git a/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestVue.java b/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestVue.java new file mode 100644 index 0000000000..c9f2fec318 --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/src/org/eclipse/wildwebdeveloper/tests/TestVue.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * Copyright (c) 2023 Dawid Pakuła and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dawid Pakuła - initial implementation + *******************************************************************************/ +package org.eclipse.wildwebdeveloper.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.lsp4e.operations.completion.LSContentAssistProcessor; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.tests.harness.util.DisplayHelper; +import org.eclipse.wildwebdeveloper.embedder.node.NodeJSManager; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class TestVue { + static IProject project; + static IFolder componentFolder; + + @BeforeAll + public static void setUp() throws Exception { + AllCleanRule.closeIntro(); + AllCleanRule.enableLogging(); + + project = Utils.provisionTestProject("vue-app"); + ProcessBuilder builder = new ProcessBuilder(NodeJSManager.getNpmLocation().getAbsolutePath(), "install", + "--no-bin-links", "--ignore-scripts").directory(project.getLocation().toFile()); + Process process = builder.start(); + System.out.println(builder.command().toString()); + String result = new BufferedReader(new InputStreamReader(process.getErrorStream())).lines() + .collect(Collectors.joining("\n")); + System.out.println("Error Stream: >>>\n" + result + "\n<<<"); + + result = new BufferedReader(new InputStreamReader(process.getInputStream())).lines() + .collect(Collectors.joining("\n")); + System.out.println("Output Stream: >>>\n" + result + "\n<<<"); + + assertEquals(0, process.waitFor(), "npm install didn't complete property"); + + project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); + assertTrue(project.exists()); + componentFolder = project.getFolder("src").getFolder("components"); + assertTrue(componentFolder.exists()); + } + + @BeforeEach + public void setUpTestCase() { + AllCleanRule.enableLogging(); + } + + @AfterAll + public static void tearDown() throws Exception { + new AllCleanRule().afterEach(null); + } + + @Test + void testVueApp() throws Exception { + IFile appComponentFile = project.getFile("src/App.vue"); + TextEditor editor = (TextEditor) IDE + .openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), appComponentFile); + DisplayHelper.sleep(4000); // Give time for LS to initialize enough before making edit and sending a + // didChange + assertTrue(new DisplayHelper() { + @Override + protected boolean condition() { + try { + return Arrays + .stream(appComponentFile.findMarkers("org.eclipse.lsp4e.diagnostic", true, + IResource.DEPTH_ZERO)) + .anyMatch(marker -> marker.getAttribute(IMarker.MESSAGE, "").contains("never read")); + } catch (CoreException e) { + e.printStackTrace(); + return false; + } + } + }.waitForCondition(editor.getSite().getShell().getDisplay(), 30000), + "Diagnostic not published in standalone component file"); + IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); + LSContentAssistProcessor contentAssistProcessor = new LSContentAssistProcessor(); + ICompletionProposal[] proposals = contentAssistProcessor.computeCompletionProposals(Utils.getViewer(editor), + document.get().indexOf(" }}")); + Optional proposal = Arrays.stream(proposals) + .filter(item -> item.getDisplayString().equals("appParameter")).findFirst(); + + assertTrue(proposal.isPresent(), "Proposal not exists"); + proposal.get().apply(document); + + assertTrue(document.get().contains("{{ appParameter }}"), "Incorrect completion insertion"); + + editor.close(false); + } + + @Test + void testVueTemplate() throws Exception { + TextEditor editor = (TextEditor) IDE.openEditor( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), + componentFolder.getFile("HelloWorld.vue")); + DisplayHelper.sleep(4000); // Give time for LS to initialize enough before making edit and sending a + // didChange + IFile appComponentHTML = componentFolder.getFile("HelloWorld.vue"); + editor = (TextEditor) IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), + appComponentHTML); + // Give some time for LS to load + DisplayHelper.sleep(2000); + // then make an edit + IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); + document.set(document.get() + "\n"); + assertTrue(new DisplayHelper() { + @Override + protected boolean condition() { + IMarker[] markers; + try { + markers = appComponentHTML.findMarkers("org.eclipse.lsp4e.diagnostic", true, IResource.DEPTH_ZERO); + return Arrays.stream(markers).anyMatch( + marker -> marker.getAttribute(IMarker.MESSAGE, "").contains("Element is missing end tag.")); + } catch (CoreException e) { + e.printStackTrace(); + return false; + } + } + }.waitForCondition(editor.getSite().getShell().getDisplay(), 30000), + "No error found on erroneous HTML component file"); + // test completion + LSContentAssistProcessor contentAssistProcessor = new LSContentAssistProcessor(); + ICompletionProposal[] proposals = contentAssistProcessor.computeCompletionProposals(Utils.getViewer(editor), + document.get().indexOf("") + " ".length() - 1); + proposals[0].apply(document); + assertEquals(new String(componentFolder.getFile("HelloWorldCorrect.vue").getContents().readAllBytes()).trim(), + document.get().trim(), "Incorrect completion insertion"); + } +} diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/.gitignore b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/.gitignore new file mode 100644 index 0000000000..403adbc1e5 --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +node_modules +/dist + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/babel.config.js b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/babel.config.js new file mode 100644 index 0000000000..e9558405fd --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + '@vue/cli-plugin-babel/preset' + ] +} diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/jsconfig.json b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/jsconfig.json new file mode 100644 index 0000000000..4aafc5f6ed --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/jsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "esnext", + "baseUrl": "./", + "moduleResolution": "node", + "paths": { + "@/*": [ + "src/*" + ] + }, + "lib": [ + "esnext", + "dom", + "dom.iterable", + "scripthost" + ] + } +} diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/package.json b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/package.json new file mode 100644 index 0000000000..002074bf91 --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/package.json @@ -0,0 +1,43 @@ +{ + "name": "vue-app", + "version": "0.1.0", + "private": true, + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build", + "lint": "vue-cli-service lint" + }, + "dependencies": { + "core-js": "^3.8.3", + "vue": "^3.2.13" + }, + "devDependencies": { + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", + "@vue/cli-plugin-babel": "~5.0.0", + "@vue/cli-plugin-eslint": "~5.0.0", + "@vue/cli-service": "~5.0.0", + "eslint": "^7.32.0", + "eslint-plugin-vue": "^8.0.3" + }, + "eslintConfig": { + "root": true, + "env": { + "node": true + }, + "extends": [ + "plugin:vue/vue3-essential", + "eslint:recommended" + ], + "parserOptions": { + "parser": "@babel/eslint-parser" + }, + "rules": {} + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not dead", + "not ie 11" + ] +} diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/public/index.html b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/public/index.html new file mode 100644 index 0000000000..8d8af105f0 --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/public/index.html @@ -0,0 +1,16 @@ + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + +
+ + + diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/App.vue b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/App.vue new file mode 100644 index 0000000000..e6842dbe86 --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/App.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorld.vue b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorld.vue new file mode 100644 index 0000000000..82c38f48c2 --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorld.vue @@ -0,0 +1,29 @@ + + + \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorldCorrect.vue b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorldCorrect.vue new file mode 100644 index 0000000000..5c41b81a33 --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/components/HelloWorldCorrect.vue @@ -0,0 +1,29 @@ + + + \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/main.js b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/main.js new file mode 100644 index 0000000000..01433bca2a --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/src/main.js @@ -0,0 +1,4 @@ +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/vue.config.js b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/vue.config.js new file mode 100644 index 0000000000..910e297e0f --- /dev/null +++ b/org.eclipse.wildwebdeveloper.tests/testProjects/vue-app/vue.config.js @@ -0,0 +1,4 @@ +const { defineConfig } = require('@vue/cli-service') +module.exports = defineConfig({ + transpileDependencies: true +}) diff --git a/org.eclipse.wildwebdeveloper/grammars/vue/Readme.md b/org.eclipse.wildwebdeveloper/grammars/vue/Readme.md new file mode 100644 index 0000000000..73834c76e8 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/grammars/vue/Readme.md @@ -0,0 +1 @@ +This is a copy from https://github.com/vuejs/language-tools/tree/master/packages/vscode-vue/syntaxes/ diff --git a/org.eclipse.wildwebdeveloper/grammars/vue/markdown-vue.json b/org.eclipse.wildwebdeveloper/grammars/vue/markdown-vue.json new file mode 100644 index 0000000000..198ebdd6ef --- /dev/null +++ b/org.eclipse.wildwebdeveloper/grammars/vue/markdown-vue.json @@ -0,0 +1,39 @@ +{ + "$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" + } + }, + "endCaptures": { + "3": { + "name": "punctuation.definition.markdown" + } + }, + "patterns": [ + { + "include": "source.vue" + } + ] + } + }, + "scopeName": "markdown.vue.codeblock" +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/grammars/vue/vue-directives.json b/org.eclipse.wildwebdeveloper/grammars/vue/vue-directives.json new file mode 100644 index 0000000000..eda55d5b58 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/grammars/vue/vue-directives.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "fileTypes": [], + "injectionSelector": "L:meta.tag -meta.attribute -entity.name.tag.pug -attribute_value -source.tsx -source.js.jsx, L:meta.element -meta.attribute", + "patterns": [ + { + "include": "source.vue#vue-directives" + } + ], + "scopeName": "vue.directives" +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/grammars/vue/vue-interpolations.json b/org.eclipse.wildwebdeveloper/grammars/vue/vue-interpolations.json new file mode 100644 index 0000000000..494396cf1e --- /dev/null +++ b/org.eclipse.wildwebdeveloper/grammars/vue/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": "source.vue#vue-interpolations" + } + ], + "scopeName": "vue.interpolations" +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/grammars/vue/vue-sfc-style-variable-injection.json b/org.eclipse.wildwebdeveloper/grammars/vue/vue-sfc-style-variable-injection.json new file mode 100644 index 0000000000..e392cae0ab --- /dev/null +++ b/org.eclipse.wildwebdeveloper/grammars/vue/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" +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/grammars/vue/vue.tmLanguage.json b/org.eclipse.wildwebdeveloper/grammars/vue/vue.tmLanguage.json new file mode 100644 index 0000000000..f4e783a902 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/grammars/vue/vue.tmLanguage.json @@ -0,0 +1,1237 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Vue", + "scopeName": "source.vue", + "patterns": [ + { + "include": "text.html.basic#comment" + }, + { + "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": "()", + "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": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)html\\b\\2)", + "beginCaptures": { + "1": { + "name": "entity.name.tag.$1.html.vue" + } + }, + "end": "()", + "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.derivative", + "patterns": [ + { + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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.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": "()", + "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": "()", + "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.tsx", + "patterns": [ + { + "include": "source.tsx" + } + ] + } + ] + }, + { + "begin": "([a-zA-Z0-9:-]+)\\b(?=[^>]*\\blang\\s*=\\s*(['\"]?)json\\b\\2)", + "beginCaptures": { + "1": { + "name": "entity.name.tag.$1.html.vue" + } + }, + "end": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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": "()", + "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.vue", + "patterns": [ + { + "include": "source.vue" + } + ] + } + ] + }, + { + "begin": "(template)\\b", + "beginCaptures": { + "1": { + "name": "entity.name.tag.$1.html.vue" + } + }, + "end": "()", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.html.vue" + }, + "2": { + "name": "entity.name.tag.$2.html.vue" + } + }, + "patterns": [ + { + "include": "#tag-stuff" + }, + { + "begin": "(?<=>)", + "end": "(?=<\\/template\\b)", + "name": "text.html.derivative", + "patterns": [ + { + "include": "#html-stuff" + } + ] + } + ] + }, + { + "begin": "(script)\\b", + "beginCaptures": { + "1": { + "name": "entity.name.tag.$1.html.vue" + } + }, + "end": "()", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.html.vue" + }, + "2": { + "name": "entity.name.tag.$2.html.vue" + } + }, + "patterns": [ + { + "include": "#tag-stuff" + }, + { + "begin": "(?<=>)", + "end": "(?=<\\/script\\b)", + "name": "source.js", + "patterns": [ + { + "include": "source.js" + } + ] + } + ] + }, + { + "begin": "(style)\\b", + "beginCaptures": { + "1": { + "name": "entity.name.tag.$1.html.vue" + } + }, + "end": "()", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.html.vue" + }, + "2": { + "name": "entity.name.tag.$2.html.vue" + } + }, + "patterns": [ + { + "include": "#tag-stuff" + }, + { + "begin": "(?<=>)", + "end": "(?=<\\/style\\b)", + "name": "source.css", + "patterns": [ + { + "include": "source.css" + } + ] + } + ] + }, + { + "begin": "([a-zA-Z0-9:-]+)", + "beginCaptures": { + "1": { + "name": "entity.name.tag.$1.html.vue" + } + }, + "end": "()", + "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": { + "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": "(?=/>)|(()", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.end.html.vue" + } + }, + "name": "meta.template-tag.start", + "patterns": [ + { + "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-style-attr" + }, + { + "include": "#vue-directives-original" + }, + { + "include": "#vue-directives-generic-attr" + } + ] + }, + "vue-directives-original": { + "begin": "(?:\\b(v-)|(:)|(@)|(#))(\\[?)([\\w\\-]*)(\\]?)(?:\\.([\\w\\-]*))*", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.html.vue" + }, + "2": { + "name": "punctuation.attribute-shorthand.bind.html.vue" + }, + "3": { + "name": "punctuation.attribute-shorthand.event.html.vue" + }, + "4": { + "name": "punctuation.attribute-shorthand.slot.html.vue" + }, + "5": { + "name": "punctuation.separator.key-value.html.vue" + }, + "6": { + "name": "entity.other.attribute-name.html.vue" + }, + "7": { + "name": "punctuation.separator.key-value.html.vue" + }, + "8": { + "name": "entity.other.attribute-name.html.vue" + }, + "9": { + "name": "punctuation.separator.key-value.html.vue" + } + }, + "end": "(?=\\s*+[^=\\s])", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.html.vue" + } + }, + "name": "meta.attribute.directive.vue", + "patterns": [ + { + "include": "#vue-directives-expression" + } + ] + }, + "vue-directives-control": { + "begin": "(v-for)|(v-if|v-else-if|v-else)", + "captures": { + "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" + } + ] + } + ] + }, + { + "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" + } + ] + } + ] + } + ] + }, + "vue-directives-style-attr": { + "begin": "\\b(style)\\s*(=)", + "captures": { + "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" + } + ] + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/language-configurations/vue/Readme.md b/org.eclipse.wildwebdeveloper/language-configurations/vue/Readme.md new file mode 100644 index 0000000000..24b351ab24 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/language-configurations/vue/Readme.md @@ -0,0 +1 @@ +This is a copy from https://github.com/vuejs/language-tools/tree/master/packages/vscode-vue/languages \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/language-configurations/vue/markdown-language-configuration.json b/org.eclipse.wildwebdeveloper/language-configurations/vue/markdown-language-configuration.json new file mode 100644 index 0000000000..ccd6f4cb4c --- /dev/null +++ b/org.eclipse.wildwebdeveloper/language-configurations/vue/markdown-language-configuration.json @@ -0,0 +1,56 @@ +{ + "autoClosingPairs": [ + // html + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "'", + "close": "'" + }, + { + "open": "\"", + "close": "\"" + }, + { + "open": "", + "notIn": [ + "comment", + "string" + ] + }, + // javascript + // commented to fix https://github.com/vuejs/language-tools/issues/1428 + // { + // "open": "`", + // "close": "`", + // "notIn": [ + // "string", + // "comment" + // ] + // }, + { + "open": "/**", + "close": " */", + "notIn": [ + "string" + ] + } + ], + "colorizedBracketPairs": [ + [ + "{{", + "}}" + ], + ] +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/language-configurations/vue/sfc-template-language-configuration.json b/org.eclipse.wildwebdeveloper/language-configurations/vue/sfc-template-language-configuration.json new file mode 100644 index 0000000000..70fc485003 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/language-configurations/vue/sfc-template-language-configuration.json @@ -0,0 +1,8 @@ +{ + "colorizedBracketPairs": [ + [ + "{{", + "}}" + ], + ] +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/language-configurations/vue/vue-language-configuration.json b/org.eclipse.wildwebdeveloper/language-configurations/vue/vue-language-configuration.json new file mode 100644 index 0000000000..c0a0494dbd --- /dev/null +++ b/org.eclipse.wildwebdeveloper/language-configurations/vue/vue-language-configuration.json @@ -0,0 +1,145 @@ +{ + "comments": { + "blockComment": [ + "" + ] + }, + "brackets": [ + [ + "" + ], + [ + "<", + ">" + ], + [ + "{", + "}" + ], + [ + "(", + ")" + ] + ], + "autoClosingPairs": [ + // html + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "'", + "close": "'" + }, + { + "open": "\"", + "close": "\"" + }, + { + "open": "", + "notIn": [ + "comment", + "string" + ] + }, + // javascript + { + "open": "`", + "close": "`", + "notIn": [ + "string", + "comment" + ] + }, + { + "open": "/**", + "close": " */", + "notIn": [ + "string" + ] + } + ], + "autoCloseBefore": ";:.,=}])><`'\" \n\t", + "surroundingPairs": [ + // html + { + "open": "'", + "close": "'" + }, + { + "open": "\"", + "close": "\"" + }, + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "<", + "close": ">" + }, + // javascript + [ + "`", + "`" + ], + ], + "colorizedBracketPairs": [], + "folding": { + "markers": { + "start": "^\\s*", + "end": "^\\s*" + } + }, + "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)", + "onEnterRules": [ + { + "beforeText": { + "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script|style))([_:\\w][_:\\w-.\\d]*)(?:(?:[^'\"/>]|\"[^\"]*\"|'[^']*')*?(?!\\/)>)[^<]*$", + "flags": "i" + }, + "afterText": { + "pattern": "^<\\/([_:\\w][_:\\w-.\\d]*)\\s*>", + "flags": "i" + }, + "action": { + "indent": "indentOutdent" + } + }, + { + "beforeText": { + "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script|style))([_:\\w][_:\\w-.\\d]*)(?:(?:[^'\"/>]|\"[^\"]*\"|'[^']*')*?(?!\\/)>)[^<]*$", + "flags": "i" + }, + "action": { + "indent": "indent" + } + } + ], + // https://github.com/vuejs/language-tools/issues/1762 + "indentationRules": { + // "increaseIndentPattern": "<(?!\\?|(?:area|base|br|col|frame|hr|html|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script|style)\\b|[^>]*\\/>)([-_\\.A-Za-z0-9]+)(?=\\s|>)\\b[^>]*>(?!.*<\\/\\1>)|)|\\{[^}\"']*$", + // add (?!\\s*\\() to fix https://github.com/vuejs/language-tools/issues/1847#issuecomment-1246101071 + "increaseIndentPattern": "<(?!\\?|(?:area|base|br|col|frame|hr|html|img|input|keygen|link|menuitem|meta|param|source|track|wbr|script|style)\\b|[^>]*\\/>)([-_\\.A-Za-z0-9]+)(?=\\s|>)\\b[^>]*>(?!\\s*\\()(?!.*<\\/\\1>)|)|\\{[^}\"']*$", + "decreaseIndentPattern": "^\\s*(<\\/(?!html)[-_\\.A-Za-z0-9]+\\b[^>]*>|-->|\\})" + } +} \ No newline at end of file diff --git a/org.eclipse.wildwebdeveloper/package.json b/org.eclipse.wildwebdeveloper/package.json index 6eaea359a9..606007405f 100644 --- a/org.eclipse.wildwebdeveloper/package.json +++ b/org.eclipse.wildwebdeveloper/package.json @@ -14,6 +14,7 @@ "vscode-json-languageserver": "file:target/vscode-json-languageserver-1.3.4.tgz", "debugger-for-chrome": "file:target/debugger-for-chrome-4.13.0.tgz", "eslint-server": "file:target/eslint-server-2.4.1.tgz", - "node-debug2": "file:target/node-debug2-1.43.0.tgz" + "node-debug2": "file:target/node-debug2-1.43.0.tgz", + "@vue/language-server" : "1.8.3" } } diff --git a/org.eclipse.wildwebdeveloper/plugin.xml b/org.eclipse.wildwebdeveloper/plugin.xml index d5d0914091..5d8b32a240 100644 --- a/org.eclipse.wildwebdeveloper/plugin.xml +++ b/org.eclipse.wildwebdeveloper/plugin.xml @@ -719,6 +719,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - initial implementation + *******************************************************************************/ +package org.eclipse.wildwebdeveloper.vue; + +import java.util.Map; + +import org.eclipse.lsp4e.LanguageClientImpl; +import org.eclipse.lsp4j.MessageParams; +import org.eclipse.lsp4j.MessageType; + +public class VueClientImpl extends LanguageClientImpl implements VueLanguageServerExtention { + + @Override + public void projectLoadingFinish(Object object) { + // TODO should this set some state because only now stuff will work like hover.. + // or maybe even after projectLanguageService "enabled" call + logMessage(new MessageParams(MessageType.Info, "Vue project loading finished")); + } + + @Override + public void projectLoadingStart(Object object) { + logMessage(new MessageParams(MessageType.Info, "Vue project loading started")); + } + + @Override + public void projectLanguageService(Map data) { + logMessage(new MessageParams(MessageType.Info, "Language Service is " + (((Boolean)data.get("languageServiceEnabled")).booleanValue()?"":"not yet ") + "enabled for project " + data.get("projectName"))); + } + +} diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java new file mode 100644 index 0000000000..b790bbe5c0 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2023 Dawid Pakuła and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dawid Pakuła - initial implementation + *******************************************************************************/ +package org.eclipse.wildwebdeveloper.vue; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider; +import org.eclipse.wildwebdeveloper.Activator; +import org.eclipse.wildwebdeveloper.embedder.node.NodeJSManager; + +public class VueLanguageServer extends ProcessStreamConnectionProvider { + + + public VueLanguageServer() { + + List commands = new ArrayList<>(); + commands.add(NodeJSManager.getNodeJsLocation().getAbsolutePath()); + try { + URL url = FileLocator + .toFileURL(getClass().getResource("/node_modules/@vue/language-server/bin/vue-language-server.js")); + commands.add(new java.io.File(url.getPath()).getAbsolutePath()); + commands.add("--stdio"); + setCommands(commands); + setWorkingDirectory(System.getProperty("user.dir")); + } catch (IOException e) { + Activator.getDefault().getLog().log( + new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), e.getMessage(), e)); + } + } + + @Override + protected ProcessBuilder createProcessBuilder() { + ProcessBuilder builder = super.createProcessBuilder(); + builder.environment().put("VUE_NONPOLLING_WATCHER", Boolean.toString(true)); + return builder; + } + + @Override + public Object getInitializationOptions(URI rootUri) { + + try { + URL url = FileLocator.toFileURL(getClass().getResource("/node_modules/typescript/lib")); + System.out.println(new File(url.getPath()).getAbsolutePath()); + return Collections.singletonMap("typescript", Collections.singletonMap("tsdk", new File(url.getPath()).getAbsolutePath())); + } catch (IOException e) { + } + return null; + } + + @Override + public String toString() { + return "VUE Language Server: " + super.toString(); + } +} diff --git a/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java new file mode 100644 index 0000000000..6994da1036 --- /dev/null +++ b/org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2023 Dawid Pakuła and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dawid Pakuła - initial implementation + *******************************************************************************/ +package org.eclipse.wildwebdeveloper.vue; + +import java.util.Map; + +import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; + +public interface VueLanguageServerExtention { + + @JsonNotification(value = "vue/projectLoadingStart") + public void projectLoadingStart(Object object); + + @JsonNotification(value = "vue/projectLoadingFinish") + public void projectLoadingFinish(Object object); + + @JsonNotification(value = "vue/projectLanguageService") + public void projectLanguageService(Map data); +}