├── .drone.yml ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.gradle ├── config ├── checkstyle │ ├── checkstyle.xml │ └── required-header.txt └── codenarc │ ├── ruleset-test.groovy │ └── ruleset.groovy ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.plugin ├── settings.gradle └── src ├── functionalTest ├── groovy │ └── com │ │ └── devsoap │ │ ├── spock │ │ └── Smoke.groovy │ │ └── vaadinflow │ │ ├── ClientDependenciesTest.groovy │ │ ├── ComponentTests.groovy │ │ ├── CreateProjectTest.groovy │ │ ├── FunctionalTest.groovy │ │ ├── GradleVersionSmokeTest.groovy │ │ ├── GroovyProjectTest.groovy │ │ ├── KotlinProjectTest.groovy │ │ ├── LegacyClientDependenciesTest.groovy │ │ ├── LegacyClientProductionModeConfigTest.groovy │ │ ├── LegacyClientProductionModeTest.groovy │ │ ├── MultimoduleFunctionalTest.groovy │ │ ├── ThemeTest.groovy │ │ ├── VaadinAsSubmoduleTest.groovy │ │ ├── VaadinFlowPluginTest.groovy │ │ ├── VaadinVersionSmokeTest.groovy │ │ └── WarArchiveTest.groovy └── resources │ ├── AllTestsConfig.groovy │ ├── ClientDependenciesTestsConfig.groovy │ ├── ClientProductionModeConfigTestsConfig.groovy │ ├── ClientProductionModeTestsConfig.groovy │ ├── SmokeTestsConfig.groovy │ └── UncategorizedTestsConfig.groovy ├── main ├── groovy │ └── com │ │ └── devsoap │ │ └── vaadinflow │ │ ├── NodePlugin.groovy │ │ ├── VaadinFlowPlugin.groovy │ │ ├── actions │ │ ├── GrettyDeprecatedPluginAction.groovy │ │ ├── GrettyPluginAction.groovy │ │ ├── JavaPluginAction.groovy │ │ ├── NodePluginAction.groovy │ │ ├── PluginAction.groovy │ │ ├── SassJavaPluginAction.groovy │ │ ├── SassWarPluginAction.groovy │ │ ├── SpringBootAction.groovy │ │ ├── VaadinFlowPluginAction.groovy │ │ ├── WarPluginAction.groovy │ │ └── package-info.groovy │ │ ├── creators │ │ ├── ComponentCreator.groovy │ │ ├── VaadinProjectCreator.groovy │ │ ├── VaadinThemeCreator.groovy │ │ └── package-info.groovy │ │ ├── extensions │ │ ├── VaadinClientDependenciesExtension.groovy │ │ ├── VaadinFlowPluginExtension.groovy │ │ └── package-info.groovy │ │ ├── models │ │ ├── ApplicationType.groovy │ │ ├── ClassModel.groovy │ │ ├── ClientPackage.groovy │ │ ├── Component.groovy │ │ ├── Composite.groovy │ │ ├── PolymerBuild.groovy │ │ ├── ProjectType.groovy │ │ ├── TemplateModel.groovy │ │ ├── VaadinProject.groovy │ │ ├── WebComponent.groovy │ │ ├── WebTemplate.groovy │ │ └── package-info.groovy │ │ ├── package-info.groovy │ │ ├── tasks │ │ ├── AssembleClientDependenciesTask.groovy │ │ ├── ConvertGroovyTemplatesToHTML.groovy │ │ ├── CreateComponentTask.groovy │ │ ├── CreateCompositeTask.groovy │ │ ├── CreateProjectTask.groovy │ │ ├── CreateWebComponentTask.groovy │ │ ├── CreateWebTemplateTask.groovy │ │ ├── InstallBowerDependenciesTask.groovy │ │ ├── InstallYarnDependenciesTask.groovy │ │ ├── NodeSetupTask.groovy │ │ ├── TranspileDependenciesTask.groovy │ │ ├── VersionCheckTask.groovy │ │ ├── WrapCssTask.groovy │ │ └── package-info.groovy │ │ └── util │ │ ├── ClassIntrospectionUtils.groovy │ │ ├── ClientPackageUtils.groovy │ │ ├── HttpUtils.groovy │ │ ├── LogUtils.groovy │ │ ├── PackagingUtil.groovy │ │ ├── TemplateWriter.groovy │ │ ├── VaadinYarnRunner.groovy │ │ ├── Versions.groovy │ │ ├── WebJarHelper.groovy │ │ └── package-info.groovy └── resources │ ├── templates │ ├── .npmrc.template │ ├── .yarnrc.template │ ├── AppTheme.css.template │ ├── AppView.groovy.template │ ├── AppView.java.template │ ├── AppView.kt.template │ ├── AppView.v14.groovy.template │ ├── AppView.v14.java.template │ ├── AppView.v14.kt.template │ ├── Component.groovy.template │ ├── Component.java.template │ ├── Component.kt.template │ ├── Composite.groovy.template │ ├── Composite.java.template │ ├── Composite.kt.template │ ├── HelloButton.groovy.template │ ├── HelloButton.java.template │ ├── HelloButton.kt.template │ ├── Servlet.groovy.template │ ├── Servlet.java.template │ ├── Servlet.kt.template │ ├── SpringBootApplication.groovy.template │ ├── SpringBootApplication.java.template │ ├── SpringBootApplication.kt.template │ ├── UI.groovy.template │ ├── UI.java.template │ ├── UI.kt.template │ ├── WebComponent.groovy.template │ ├── WebComponent.java.template │ ├── WebComponent.kt.template │ ├── WebComponent.v14.groovy.template │ ├── WebComponent.v14.java.template │ ├── WebComponent.v14.kt.template │ ├── WebTemplate.groovy.template │ ├── WebTemplate.html.template │ ├── WebTemplate.java.template │ ├── WebTemplate.js.template │ ├── WebTemplate.kt.template │ ├── WebTemplate.tpl.template │ ├── WebTemplate.v14.groovy.template │ ├── WebTemplate.v14.java.template │ ├── WebTemplate.v14.kt.template │ ├── hello-button.js.template │ ├── theme.js.template │ ├── webpack.config.js.template │ └── yarn-flat.js.template │ ├── vaadin-plugin.gdsl │ └── versions.properties └── test └── groovy └── com └── devsoap └── vaadinflow └── util └── VaadinYarnRunnerTest.groovy /.drone.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2020 Devsoap Inc. 2 | # 3 | # Licensed under the Creative Commons Attribution-NoDerivatives 4.0 4 | # International Public License (the "License"); you may not use this file 5 | # except in compliance with the License. 6 | # 7 | # You may obtain a copy of the License at 8 | # 9 | # https://creativecommons.org/licenses/by-nd/4.0/ 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | kind: pipeline 18 | name: default 19 | type: docker 20 | 21 | steps: 22 | 23 | - name: Build Plugin 24 | image: gradle:jdk8 25 | volumes: 26 | - name: gradle 27 | path: /home/gradle/.gradle 28 | commands: 29 | - ./gradlew assemble 30 | environment: 31 | ORG_GRADLE_PROJECT_BUILD_VERSION: ${DRONE_TAG} 32 | DEVSOAP_EMAIL: 33 | from_secret: DEVSOAP_EMAIL 34 | DEVSOAP_KEY: 35 | from_secret: DEVSOAP_KEY 36 | 37 | - name: Run Basic Tests 38 | image: gradle:jdk8 39 | volumes: 40 | - name: gradle 41 | path: /home/gradle/.gradle 42 | commands: 43 | - ./gradlew --stacktrace --info check 44 | environment: 45 | ORG_GRADLE_PROJECT_BUILD_VERSION: ${DRONE_TAG} 46 | DEVSOAP_EMAIL: 47 | from_secret: DEVSOAP_EMAIL 48 | DEVSOAP_KEY: 49 | from_secret: DEVSOAP_KEY 50 | when: 51 | not: 52 | target: 53 | - production 54 | 55 | - name: Run Functional Tests 56 | image: gradle:jdk8 57 | volumes: 58 | - name: gradle 59 | path: /home/gradle/.gradle 60 | commands: 61 | - apt-get update -y 62 | - apt-get install -y build-essential 63 | - ./gradlew --stacktrace --info --parallel functionalTest 64 | environment: 65 | ORG_GRADLE_PROJECT_BUILD_VERSION: ${DRONE_TAG} 66 | DEVSOAP_EMAIL: 67 | from_secret: DEVSOAP_EMAIL 68 | DEVSOAP_KEY: 69 | from_secret: DEVSOAP_KEY 70 | when: 71 | target: 72 | - tests 73 | 74 | - name: Build Documentation 75 | image: gradle:jdk8 76 | volumes: 77 | - name: gradle 78 | path: /home/gradle/.gradle 79 | commands: 80 | - ./gradlew groovyDoc 81 | environment: 82 | ORG_GRADLE_PROJECT_BUILD_VERSION: ${DRONE_TAG} 83 | DEVSOAP_EMAIL: 84 | from_secret: DEVSOAP_EMAIL 85 | DEVSOAP_KEY: 86 | from_secret: DEVSOAP_KEY 87 | when: 88 | target: 89 | - production 90 | 91 | - name: Publish Plugin 92 | image: gradle:jdk8 93 | volumes: 94 | - name: gradle 95 | path: /home/gradle/.gradle 96 | commands: 97 | - ./gradlew -Dgradle.publish.key=$${GRADLE_PUBLISH_KEY} -Dgradle.publish.secret=$${GRADLE_PUBLISH_SECRET} publishPlugins 98 | environment: 99 | ORG_GRADLE_PROJECT_BUILD_VERSION: ${DRONE_TAG} 100 | GRADLE_PUBLISH_KEY: 101 | from_secret: GRADLE_PUBLISH_KEY 102 | GRADLE_PUBLISH_SECRET: 103 | from_secret: GRADLE_PUBLISH_SECRET 104 | DEVSOAP_EMAIL: 105 | from_secret: DEVSOAP_EMAIL 106 | DEVSOAP_KEY: 107 | from_secret: DEVSOAP_KEY 108 | when: 109 | target: 110 | - production 111 | 112 | - name: Publish Documentation 113 | image: drone/git 114 | commands: 115 | - git clone --depth=1 https://$${GITHUB_USERNAME}:$${GITHUB_PUSH_TOKEN}@github.com/devsoap/docs.git build/repo/docs 116 | - cp -R build/docs/groovydoc build/repo/docs/docs/_vaadin_flow_gradle_plugin_api 117 | - cd build/repo/docs 118 | - git config user.email 'ci@devsoap.com' 119 | - git config user.name 'Devsoap Build Bot' 120 | - git checkout -b vaadin-flow-gradle-plugin/$${DRONE_TAG} 121 | - git add docs/_vaadin_flow_gradle_plugin_api 122 | - git commit -m "Update API documentation for Vaadin Flow Gradle Plugin ${DRONE_TAG}" 123 | - git push origin vaadin-flow-gradle-plugin/$${DRONE_TAG} 124 | environment: 125 | GITHUB_USERNAME: 126 | from_secret: GITHUB_USERNAME 127 | GITHUB_PUSH_TOKEN: 128 | from_secret: GITHUB_PUSH_TOKEN 129 | when: 130 | target: 131 | - production 132 | 133 | - name: Cleanup 134 | image: gradle:jdk8 135 | volumes: 136 | - name: gradle 137 | path: /home/gradle/.gradle 138 | commands: 139 | - rm -rf build 140 | - ./gradlew clean 141 | - ./gradlew --stop 142 | environment: 143 | ORG_GRADLE_PROJECT_BUILD_VERSION: ${DRONE_TAG} 144 | 145 | trigger: 146 | ref: 147 | include: 148 | - refs/tags/** 149 | 150 | volumes: 151 | - name: gradle 152 | host: 153 | path: /tmp/drone/gradle -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://devsoap.com/store 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Desktop (please complete the following information):** 8 | - OS: [e.g. Windows, Ubuntu, iOS] 9 | - JDK version: [e.g. 8,9,10,11,12] 10 | - Gradle version: [e.g. 4.10.2] 11 | - Vaadin Plugin version: [e.g. 1.0.0.M6] 12 | 13 | **Describe the bug** 14 | A clear and concise description of what the bug is. 15 | 16 | **To Reproduce** 17 | Steps to reproduce the behavior: 18 | 1. Setup project '...' 19 | 2. Run Gradle task '....'' 20 | 4. See error '....' 21 | 22 | **Expected behavior** 23 | A clear and concise description of what you expected to happen. 24 | 25 | **Screenshots** 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | **Additional context** 29 | Add any other context about the problem here. 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | build 4 | .gradle 5 | out 6 | yarn-cache 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: groovy 2 | jdk: 3 | - openjdk11 4 | script: "./gradlew --build-cache --stacktrace --info --parallel check -PTEST_CATEGORY=$TEST_CATEGORY" 5 | env: 6 | - TEST_CATEGORY=SmokeTests 7 | - TEST_CATEGORY=UncategorizedTests 8 | - TEST_CATEGORY=ClientDependenciesTests 9 | - TEST_CATEGORY=ClientProductionModeConfigTests 10 | - TEST_CATEGORY=ClientProductionModeTests 11 | 12 | branches: 13 | only: 14 | - "master" 15 | before_cache: 16 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 17 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 18 | cache: 19 | directories: 20 | - $HOME/.gradle/caches/ 21 | - $HOME/.gradle/wrapper/ 22 | - ./yarn-cache 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Development Guide 2 | 3 | To develop the plugin locally you will need to clone the sources of the plugin. 4 | 5 | You can do it by just cloning this repository: 6 | 7 | ```bash 8 | $> git clone https://github.com/devsoap/gradle-vaadin-flow.git 9 | ``` 10 | 11 | The project is a Gradle project so you can just import it into your preferred IDE. 12 | 13 | The plugin is written in the Groovy programming language. 14 | 15 | #### Source structure 16 | 17 | The project has 3 source folders. 18 | 19 | The **src/main** source folder contains the sources of the plugin. This is most likely where you will be working. 20 | 21 | The **src/test** source folders contains unit tests. 22 | 23 | The third source folder, **src/functionalTest** is for integration/functional tests. These tests are run using the Gradle Test Runner so they are run using an actual Gradle installation. The tests are written in Spock and Groovy. 24 | 25 | #### Plugin package structure 26 | 27 | The source code is split into 6 different sub packages: 28 | 29 | ##### actions 30 | 31 | Every action is related to a plugin that is applied to the project. For example, the GrettyPluginAction is only run for 32 | projects which have applied the Gretty plugin. The purpose of these actions is to configure third party plugins so they 33 | integrate in a seamless manner with the Vaadin Flow plugin. 34 | 35 | ##### creators 36 | 37 | Creators are responsible for creating files and folders for the user from pre-defined templates. They are mostly used for 38 | the *vaadinCreate\** tasks. All creator tasks operates on a model. 39 | 40 | ##### models 41 | 42 | Models provide the data for the creator tasks. They do not contain any business logic and are only meant for conveying 43 | data from one place to another. 44 | 45 | ##### extensions 46 | 47 | Extensions extend the project with configuration options. They provide the way users of the plugin configures the plugin 48 | to behave as they need. 49 | 50 | ##### tasks 51 | 52 | Tasks provide the run targets for the Gradle project. All tasks should start with *vaadin* and should be grouped in 53 | a *vaadin* group. 54 | 55 | ##### util 56 | 57 | Util contains various utilities for perform file and class traversing tasks. 58 | 59 | #### Building the plugin 60 | 61 | The plugin can be built by running the **jar** task. After a successful build the plugin artifact will be placed in the 62 | ``build/libs`` folder. 63 | 64 | #### Using the plugin from a test project 65 | 66 | 67 | The easiest way to test your changes is to create another project where you just apply the plugin. It can be an existing 68 | Vaadin project that already uses the gradle plugin or a new one. 69 | 70 | The project comes with an apply script (local.plugin) that you can use to apply the built project. 71 | 72 | In your test project replace any existing plugin with 73 | 74 | ```groovy 75 | apply from: '/local.plugin' 76 | ``` 77 | 78 | Here is an example of a complete ``build.gradle`` using this approach: 79 | 80 | ```groovy 81 | // Apply all other plugin as you normally would 82 | plugins { 83 | id "org.gretty" version '2.3.1' 84 | id 'java' 85 | } 86 | 87 | // Build the plugin jar and use the applyscript to apply it 88 | apply from: '/gradle-vaadin-flow/local.plugin' 89 | 90 | // ... Continue configuring the project as you normally would 91 | vaadin.autoconfigure() 92 | ``` 93 | 94 | You might need to tweak the paths in ``local.plugin`` to suit your environment. By default it uses 95 | ``$HOME/Repositories/gradle-vaadin-flow/build/libs`` to locate the plugin, but if you have a different path you will 96 | need to change it. Please don't submit these changes however in a pull request, the CI server requires this path. 97 | 98 | 99 | #### Running the function/integration tests 100 | 101 | The integration tests are normal JUnit tests leveraging the Spock framework. 102 | 103 | If you only want to run a single test then it can be achieved by running the following: 104 | 105 | ```bash 106 | ./gradlew -Dorg.gradle.testkit.debug=true functionalTest -x test --stacktrace --info --tests "**" 107 | ``` 108 | 109 | If you have a PRO subscription you can also add the following environment variables to be able to run the test in PRO mode: 110 | 111 | ``` 112 | DEVSOAP_EMAIL= 113 | DEVSOAP_KEY= 114 | ``` 115 | 116 | ##### Pull requests 117 | 118 | When you submit a pull request you will need to ensure two things are set: 119 | 120 | > Sign the CLA 121 | 122 | The CLA can easily be signed by just clicking on the link after you have submitted the pull request. 123 | 124 | > Ensure all functional/integration tests are green 125 | 126 | Once you submit the pull request Travis (CI) will run all the tests. If some of the fail then please fix them and try 127 | again. 128 | 129 | It is encouraged to use git rebase when pushing changes to the pull request branches as that will keep the Git history 130 | clean once the pull request is merged. 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DS Vaadin Flow Gradle Plugin 2 | 3 | The Gradle Vaadin Flow plugin allows you to easily build Vaadin 10+ projects with Gradle. It allows you to create a new 4 | projects from pre-made project templates, themes and components. It handles cross-compiling for older browsers which do 5 | not yet support ES6 and helps with integrating with other useful Gradle plugins. 6 | 7 | [![Build Status](https://api.travis-ci.org/devsoap/ds-gradle-vaadin.svg?branch=master)](https://travis-ci.org/devsoap/ds-gradle-vaadin) 8 | [![Latest Release](https://img.shields.io/github/release/devsoap/ds-gradle-vaadin.svg)](https://plugins.gradle.org/plugin/com.devsoap.vaadin-flow) 9 | [![License](https://img.shields.io/github/license/devsoap/ds-gradle-vaadin.svg)](https://creativecommons.org/licenses/by-nd/4.0/) 10 | [![](https://hits.devsoap.com/hit/ds-gradle-vaadin-github.png)](https://devsoap.com) 11 | 12 | # Getting started 13 | 14 | To get started using the plugin have a look a the plugin documentation at https://docs.devsoap.com/vaadin_flow_gradle_plugin 15 | 16 | # License 17 | 18 | This plugin is distributed under the Creative Commons Attribution-NoDerivatives 4.0 International Public License. For more 19 | information about the license see the LICENSE file in the root directory of the repository. 20 | 21 | A signed CLA is required when contributing to the project. 22 | 23 | # Contributing to the project 24 | 25 | Checkout the [Contribution Guide](CONTRIBUTING.md) to learn how to develop this project locally. 26 | 27 | -------------------------------------------------------------------------------- /config/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /config/checkstyle/required-header.txt: -------------------------------------------------------------------------------- 1 | ^/\*\s*$ 2 | ^ \* Copyright 2018-2019 Devsoap Inc.$ 3 | ^ \*\s*$ 4 | ^ \* Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. * 7 | * You may obtain a copy of the License at 8 | * 9 | * https://creativecommons.org/licenses/by-nd/4.0/ 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsoap/ds-gradle-vaadin/1b849ee1760dc6e4666c5c514df80005b1a6886e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /local.plugin: -------------------------------------------------------------------------------- 1 | /* 2 | * Bootstrap script for the Plugin. 3 | * 4 | * The script will add the latest version of the plugin to the build script 5 | * dependencies and apply the plugin to the project. If you do not want 6 | * this behaviour you can copy&paste the below configuration into your 7 | * own build script and define your own repository and version for the plugin. 8 | * 9 | * Note: This script is only intended for use when developing the plugin itself 10 | */ 11 | buildscript { 12 | def gradlePluginDirectory = System.getProperty("user.home") + '/Repositories/ds-gradle-vaadin/build/libs' 13 | def pluginVersion = '2.0-SNAPSHOT-'+ new Date().format('yyyyMMdd') 14 | repositories { 15 | mavenCentral() 16 | maven { 17 | url "https://plugins.gradle.org/m2/" 18 | } 19 | flatDir dirs: gradlePluginDirectory 20 | } 21 | 22 | dependencies { 23 | classpath "com.devsoap:gradle-vaadin-flow-plugin:$pluginVersion" 24 | classpath "com.moowork.gradle:gradle-node-plugin:1.2.0" 25 | classpath "com.devsoap:devsoap-license-plugin:1.0.16" 26 | classpath 'io.github.classgraph:classgraph:4.8.49' 27 | } 28 | } 29 | 30 | repositories { 31 | def gradlePluginDirectory = System.getProperty("user.home")+'/Repositories/ds-gradle-vaadin/build/libs' 32 | def pluginVersion = '2.0-SNAPSHOT-'+ new Date().format('yyyyMMdd') 33 | flatDir dirs: gradlePluginDirectory 34 | } 35 | 36 | if (!project.plugins.findPlugin(com.devsoap.vaadinflow.VaadinFlowPlugin)) { 37 | project.apply(plugin: com.devsoap.vaadinflow.VaadinFlowPlugin) 38 | } 39 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | plugins { 19 | id "com.devsoap.cache" version "1.0.4" 20 | } 21 | 22 | devsoap { 23 | email = System.getenv('DEVSOAP_EMAIL') 24 | key = System.getenv('DEVSOAP_KEY') 25 | } 26 | 27 | buildCache { 28 | local { 29 | enabled = false 30 | } 31 | } -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/spock/Smoke.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.spock 19 | 20 | import java.lang.annotation.ElementType 21 | import java.lang.annotation.Inherited 22 | import java.lang.annotation.Retention 23 | import java.lang.annotation.RetentionPolicy 24 | import java.lang.annotation.Target 25 | 26 | /** 27 | * Annotation marking tests that are smoke tests (partially tests the full scope) 28 | * 29 | * @author John Ahlroos 30 | * @since 1.0 31 | */ 32 | @Retention(RetentionPolicy.RUNTIME) 33 | @Target([ElementType.TYPE, ElementType.METHOD]) 34 | @Inherited 35 | @interface Smoke { } 36 | -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/vaadinflow/ClientDependenciesTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import org.gradle.testkit.runner.BuildResult 21 | 22 | import java.nio.file.Paths 23 | 24 | /** 25 | * Test for testing client dependencies added to the project 26 | * 27 | * @author John Ahlroos 28 | * @since 1.3 29 | */ 30 | class ClientDependenciesTest extends FunctionalTest { 31 | 32 | void 'bundle NPM dependencies with Webpack'() { 33 | setup: 34 | compatibilityMode = false 35 | buildFile << ''' 36 | vaadin.autoconfigure() 37 | '''.stripIndent() 38 | when: 39 | run 'vaadinCreateProject' 40 | BuildResult jarResult = run('jar') 41 | File build = Paths.get(testProjectDir.root.canonicalPath, 'build').toFile() 42 | File frontend = Paths.get(build.canonicalPath, 'frontend').toFile() 43 | File dist = new File(frontend, 'dist') 44 | File scripts = new File(frontend, 'scripts') 45 | File genVaadin = Paths.get(build.canonicalPath, 'webapp-gen', 'VAADIN').toFile() 46 | File genBuild = new File(genVaadin, 'build') 47 | then: 48 | !jarResult.output.contains('Vaadin 13 (Flow 1) compatibility mode') 49 | 50 | new File(frontend, 'package.json').exists() 51 | new File(frontend, 'webpack.config.js').exists() 52 | new File(frontend, '.npmrc').exists() 53 | new File(frontend, '.yarnrc').exists() 54 | new File(scripts, 'build-dist.js').exists() 55 | new File(dist, 'package.json').exists() 56 | new File(dist, 'yarn.lock').exists() 57 | new File(genBuild, 'webcomponentsjs').exists() 58 | genVaadin.list { dir, name -> name.startsWith('vaadin-main.es5') }.length > 0 59 | genVaadin.list { dir, name -> name.startsWith('vaadin-main-') }.length > 0 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/vaadinflow/FunctionalTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import org.gradle.testkit.runner.BuildResult 21 | import org.gradle.testkit.runner.GradleRunner 22 | import org.junit.Rule 23 | import org.junit.rules.TemporaryFolder 24 | import spock.lang.Specification 25 | 26 | import java.nio.file.Paths 27 | import java.util.concurrent.TimeUnit 28 | 29 | /** 30 | * Base class for functional tests 31 | * 32 | * @author John Ahlroos 33 | * @since 1.0 34 | */ 35 | class FunctionalTest extends Specification { 36 | 37 | static final String PLUGIN_ID = 'com.devsoap.vaadin-flow' 38 | 39 | static final String DEFAULT_TEST_VAADIN_VERSION = '14.1.2' 40 | 41 | @Rule 42 | protected TemporaryFolder testProjectDir 43 | 44 | protected File buildFile 45 | 46 | protected File settingsFile 47 | 48 | private long testStart 49 | 50 | protected Map extraPlugins 51 | 52 | protected String vaadinVersion 53 | 54 | protected File getPluginJar() { 55 | Paths.get(System.getProperty('plugin.jar.path')).toFile() 56 | } 57 | 58 | protected boolean compatibilityMode = true 59 | 60 | /** 61 | * Sets up the test 62 | */ 63 | protected void setup() { 64 | extraPlugins = [:] 65 | vaadinVersion = DEFAULT_TEST_VAADIN_VERSION 66 | initBuildFile() 67 | initSettingsFile() 68 | testStart = System.currentTimeMillis() 69 | println "Running test in ${testProjectDir.root}" 70 | println "Using Yarn cache dir $offlineCachePath" 71 | } 72 | 73 | /** 74 | * Set additional plugins for the test. 75 | * 76 | * @param plugins 77 | * the plugins to add besides the Vaadin plugin 78 | */ 79 | protected void setExtraPlugins(Map plugins) { 80 | extraPlugins = plugins 81 | buildFile.delete() 82 | initBuildFile() 83 | } 84 | 85 | /** 86 | * Set the Vaadin version used in the test 87 | * 88 | * @param version 89 | * the default vaadin version to test 90 | */ 91 | protected void setVaadinVersion(String version) { 92 | vaadinVersion = version 93 | buildFile.delete() 94 | initBuildFile() 95 | } 96 | 97 | /** 98 | * Cleans up the test 99 | */ 100 | protected void cleanup() { 101 | long ms = System.currentTimeMillis() - testStart 102 | println "Test took ${TimeUnit.MILLISECONDS.toSeconds(ms)} seconds." 103 | } 104 | 105 | /** 106 | * Runs the project 107 | * 108 | * @param args 109 | * the command line arguments to pass to gradle 110 | * @return 111 | * the result of the build 112 | */ 113 | protected BuildResult run(ConfigureRunner config = { }, String... args) { 114 | System.setProperty('vaadin.compatibilityMode', compatibilityMode.toString() ) 115 | GradleRunner runner = GradleRunner.create() 116 | .withProjectDir(testProjectDir.root) 117 | .withArguments(['--stacktrace', '--info'] + (args as List)) 118 | .withPluginClasspath() 119 | config.run(runner) 120 | println "Running gradle ${runner.arguments.join(' ')}" 121 | runner.build() 122 | } 123 | 124 | /** 125 | * Runs the project and is expected to fail 126 | * 127 | * @param args 128 | * the command line arguments to pass to gradle 129 | * @return 130 | * the result of the build 131 | */ 132 | protected BuildResult runAndFail(ConfigureRunner config = { }, String... args) { 133 | System.setProperty('vaadin.compatibilityMode', compatibilityMode.toString() ) 134 | GradleRunner runner = GradleRunner.create() 135 | .withProjectDir(testProjectDir.root) 136 | .withArguments(['--stacktrace', '--info'] + (args as List)) 137 | .withPluginClasspath() 138 | config.run(runner) 139 | println "Running gradle ${args.join(' ')}" 140 | runner.buildAndFail() 141 | } 142 | 143 | protected void initBuildFile() { 144 | buildFile = testProjectDir.newFile('build.gradle') 145 | buildFile << """ 146 | plugins { 147 | id '$PLUGIN_ID' 148 | ${extraPlugins.collect { it.value ? "id '$it.key' version '$it.value'" : "id '$it.key'" }.join('\n')} 149 | } 150 | 151 | ${ vaadinVersion ? "vaadin.version = '$vaadinVersion'" : '' } 152 | 153 | vaadinClientDependencies { 154 | offlineCachePath = "$offlineCachePath" 155 | } 156 | 157 | repositories { 158 | flatDir { 159 | dirs '${pluginJar.parentFile.canonicalPath}' 160 | } 161 | } 162 | 163 | """.stripIndent() 164 | } 165 | 166 | private void initSettingsFile() { 167 | settingsFile = testProjectDir.newFile('settings.gradle') 168 | } 169 | 170 | private String getOfflineCachePath() { 171 | System.getProperty('yarn.cache.dir', Paths.get(testProjectDir.root.canonicalPath, 'yarn-cache') 172 | .toFile().canonicalPath) 173 | } 174 | 175 | /** 176 | * Interface representing a GradleRunner configuration closure 177 | */ 178 | @FunctionalInterface 179 | interface ConfigureRunner { 180 | void run(GradleRunner runner) 181 | } 182 | 183 | } 184 | -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/vaadinflow/GradleVersionSmokeTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import com.devsoap.spock.Smoke 21 | import org.gradle.testkit.runner.BuildResult 22 | import org.gradle.testkit.runner.TaskOutcome 23 | import spock.lang.Unroll 24 | 25 | /** 26 | * Smoke test for Gradle versions 27 | * 28 | * @author John Ahlroos 29 | * @since 1.0 30 | */ 31 | @Smoke 32 | class GradleVersionSmokeTest extends FunctionalTest { 33 | 34 | private static final List VERSIONS = ['6.0', '6.1', '6.2'] 35 | 36 | @Unroll 37 | void 'Test Gradle #version'(String version) { 38 | setup: 39 | buildFile << ''' 40 | vaadin.autoconfigure() 41 | '''.stripIndent() 42 | run( { it.withGradleVersion(version) }, 'vaadinCreateProject') 43 | when: 44 | BuildResult result = run( { 45 | it.withGradleVersion(version) 46 | it.arguments = ['--warning-mode', 'all'] + it.arguments 47 | }, 'jar') 48 | then: 49 | result.task(':jar').outcome == TaskOutcome.SUCCESS 50 | !result.output.contains('Deprecated Gradle features') 51 | 52 | where: 53 | version << VERSIONS 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/vaadinflow/GroovyProjectTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 21 | 22 | import org.gradle.testkit.runner.BuildResult 23 | import java.nio.file.Paths 24 | 25 | /** 26 | * Tests for Groovy projects 27 | * 28 | * @author John Ahlroos 29 | * @since 1.0 30 | */ 31 | class GroovyProjectTest extends FunctionalTest { 32 | 33 | void 'Create a Groovy project'() { 34 | setup: 35 | extraPlugins = ['groovy':''] 36 | File rootDir = testProjectDir.root 37 | File javaSourceDir = Paths.get(rootDir.canonicalPath, 'src', 'main', 'groovy').toFile() 38 | File pkg = Paths.get(javaSourceDir.canonicalPath, 'com', 'example', 39 | testProjectDir.root.name.toLowerCase()).toFile() 40 | File servletFile = Paths.get(pkg.canonicalPath, 41 | "${testProjectDir.root.name.capitalize()}Servlet.groovy").toFile() 42 | File viewFile = Paths.get(pkg.canonicalPath, 43 | "${testProjectDir.root.name.capitalize()}View.groovy").toFile() 44 | File uiFile = Paths.get(pkg.canonicalPath, 45 | "${testProjectDir.root.name.capitalize()}UI.groovy").toFile() 46 | when: 47 | BuildResult result = run 'vaadinCreateProject' 48 | then: 49 | result.task(':vaadinCreateProject').outcome == SUCCESS 50 | servletFile.exists() 51 | viewFile.exists() 52 | uiFile.exists() 53 | } 54 | 55 | void 'Groovy project compiles'() { 56 | setup: 57 | extraPlugins = ['groovy':''] 58 | buildFile << ''' 59 | vaadin.autoconfigure() 60 | '''.stripIndent() 61 | when: 62 | run'vaadinCreateProject' 63 | run 'vaadinCreateComponent' 64 | run 'vaadinCreateComposite' 65 | run 'vaadinCreateWebTemplate' 66 | run 'vaadinCreateWebComponent', '--dependency', 'bower:paper-slider:v2.0.5' 67 | 68 | BuildResult result = run'jar' 69 | then: 70 | result.task(':jar').outcome == SUCCESS 71 | } 72 | 73 | void 'Groovy template is converted'() { 74 | setup: 75 | extraPlugins = ['groovy':''] 76 | 77 | run'vaadinCreateProject' 78 | run 'vaadinCreateWebTemplate', '--name', 'groovytemplate' 79 | 80 | File gen = Paths.get(testProjectDir.root.canonicalPath, 81 | 'build', 'webapp-gen', 'frontend', 'templates').toFile() 82 | File htmlFile = new File(gen, 'groovytemplate.html') 83 | when: 84 | run 'vaadinConvertGroovyTemplatesToHtml' 85 | then: 86 | htmlFile.exists() 87 | htmlFile.text.contains("") 88 | htmlFile.text.contains("") 89 | htmlFile.text.contains("") 90 | } 91 | 92 | void 'Groovy templates are included in transpilation'() { 93 | setup: 94 | extraPlugins = ['groovy':''] 95 | 96 | run 'vaadinCreateProject' 97 | run 'vaadinCreateWebTemplate', '--name', 'groovytemplate' 98 | 99 | buildFile << ''' 100 | vaadin.productionMode = true 101 | 102 | repositories { 103 | vaadin.repositories() 104 | } 105 | 106 | dependencies { 107 | implementation vaadin.bom() 108 | implementation vaadin.core() 109 | implementation vaadin.servletApi() 110 | implementation vaadin.lumoTheme() 111 | implementation vaadin.groovy() 112 | } 113 | '''.stripIndent() 114 | when: 115 | run('vaadinTranspileDependencies') 116 | then: 117 | File frontend = Paths.get(buildFile.parentFile.canonicalPath, 'build', 'frontend').toFile() 118 | File polymerJson = new File(frontend, 'polymer.json') 119 | polymerJson.text.contains('templates/groovytemplate.html') 120 | } 121 | 122 | void 'Groovy templates in custom webapp dir'() { 123 | setup: 124 | extraPlugins = ['groovy':''] 125 | 126 | buildFile << ''' 127 | vaadinAssembleClient { 128 | webappDir 'src' 129 | } 130 | '''.stripIndent() 131 | 132 | run 'vaadinCreateProject' 133 | run 'vaadinCreateWebTemplate', '--name', 'groovytemplate' 134 | 135 | buildFile << ''' 136 | vaadin.productionMode = true 137 | 138 | repositories { 139 | vaadin.repositories() 140 | } 141 | 142 | dependencies { 143 | implementation vaadin.bom() 144 | implementation vaadin.core() 145 | implementation vaadin.servletApi() 146 | implementation vaadin.groovy() 147 | implementation vaadin.lumoTheme() 148 | } 149 | '''.stripIndent() 150 | when: 151 | run('vaadinTranspileDependencies') 152 | then: 153 | File frontend = Paths.get(buildFile.parentFile.canonicalPath, 'build', 'frontend').toFile() 154 | File polymerJson = new File(frontend, 'polymer.json') 155 | polymerJson.text.contains('templates/groovytemplate.html') 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/vaadinflow/KotlinProjectTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import static org.gradle.testkit.runner.TaskOutcome.SUCCESS 21 | 22 | import org.gradle.testkit.runner.BuildResult 23 | 24 | import java.nio.file.Paths 25 | 26 | /** 27 | * Tests for Kotlin projects 28 | * 29 | * @author John Ahlroos 30 | * @since 1.0 31 | */ 32 | class KotlinProjectTest extends FunctionalTest { 33 | 34 | void 'Create a Kotlin project'() { 35 | setup: 36 | extraPlugins = ['org.jetbrains.kotlin.jvm':'1.3.70'] 37 | File rootDir = testProjectDir.root 38 | File javaSourceDir = Paths.get(rootDir.canonicalPath, 'src', 'main', 'kotlin').toFile() 39 | File pkg = Paths.get(javaSourceDir.canonicalPath, 'com', 'example', 40 | testProjectDir.root.name.toLowerCase()).toFile() 41 | File servletFile = Paths.get(pkg.canonicalPath, 42 | "${testProjectDir.root.name.capitalize()}Servlet.kt").toFile() 43 | File viewFile = Paths.get(pkg.canonicalPath, 44 | "${testProjectDir.root.name.capitalize()}View.kt").toFile() 45 | File uiFile = Paths.get(pkg.canonicalPath, 46 | "${testProjectDir.root.name.capitalize()}UI.kt").toFile() 47 | when: 48 | BuildResult result = run 'vaadinCreateProject' 49 | then: 50 | result.task(':vaadinCreateProject').outcome == SUCCESS 51 | servletFile.exists() 52 | viewFile.exists() 53 | uiFile.exists() 54 | } 55 | 56 | void 'Kotlin project compiles'() { 57 | setup: 58 | extraPlugins = ['org.jetbrains.kotlin.jvm':'1.3.70'] 59 | buildFile << ''' 60 | vaadin.autoconfigure() 61 | '''.stripIndent() 62 | when: 63 | run'vaadinCreateProject' 64 | run 'vaadinCreateComponent' 65 | run 'vaadinCreateComposite' 66 | run 'vaadinCreateWebTemplate' 67 | run 'vaadinCreateWebComponent', '--dependency', 'bower:paper-slider:v2.0.5' 68 | 69 | BuildResult result = run'jar' 70 | then: 71 | result.task(':jar').outcome == SUCCESS 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/vaadinflow/MultimoduleFunctionalTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import org.gradle.testkit.runner.BuildResult 21 | import org.gradle.testkit.runner.GradleRunner 22 | import org.junit.Rule 23 | import org.junit.rules.TemporaryFolder 24 | import spock.lang.Specification 25 | 26 | import java.nio.file.Paths 27 | import java.util.concurrent.TimeUnit 28 | 29 | /** 30 | * Tests creation of Vaadin multi-module projects 31 | * 32 | * @author John Ahlroos 33 | * @since 1.0 34 | */ 35 | class MultimoduleFunctionalTest extends Specification { 36 | 37 | static final String PLUGIN_ID = 'com.devsoap.vaadin-flow' 38 | 39 | @Rule 40 | protected TemporaryFolder rootProjectDir 41 | protected File libraryProject 42 | protected File vaadinProject 43 | 44 | protected File buildFile 45 | protected File libraryProjectBuildFile 46 | protected File vaadinProjectBuildFile 47 | 48 | protected File settingsFile 49 | 50 | private long testStart 51 | 52 | protected String vaadinVersion = FunctionalTest.DEFAULT_TEST_VAADIN_VERSION 53 | 54 | protected String getOfflineCachePath() { 55 | System.getProperty('yarn.cache.dir', 56 | Paths.get(rootProjectDir.root.canonicalPath, 'yarn-cache').toFile().canonicalPath) 57 | } 58 | 59 | protected File getPluginJar() { 60 | Paths.get(System.getProperty('plugin.jar.path')).toFile() 61 | } 62 | 63 | protected void setup() { 64 | libraryProject = new File(rootProjectDir.root, 'libraryProject') 65 | libraryProject.mkdirs() 66 | 67 | vaadinProject = new File(rootProjectDir.root, 'vaadinProject') 68 | vaadinProject.mkdirs() 69 | 70 | buildFile = rootProjectDir.newFile('build.gradle') 71 | buildFile << """ 72 | plugins { 73 | id '$PLUGIN_ID' apply false 74 | } 75 | """.stripIndent() 76 | 77 | libraryProjectBuildFile = new File(libraryProject, 'build.gradle') 78 | libraryProjectBuildFile << """ 79 | apply plugin: 'java' 80 | """.stripIndent() 81 | 82 | vaadinProjectBuildFile = new File(vaadinProject, 'build.gradle') 83 | vaadinProjectBuildFile << """ 84 | apply plugin: '$PLUGIN_ID' 85 | 86 | vaadin.version = '$vaadinVersion' 87 | 88 | repositories { 89 | flatDir { 90 | dirs '${pluginJar.parentFile.canonicalPath}' 91 | } 92 | vaadin.repositories() 93 | } 94 | 95 | vaadinClientDependencies { 96 | offlineCachePath = "$offlineCachePath" 97 | } 98 | 99 | dependencies { 100 | compile vaadin.bom() 101 | compile vaadin.core() 102 | compile vaadin.lumoTheme() 103 | compile vaadin.servletApi() 104 | implementation project(':libraryProject') 105 | } 106 | 107 | """.stripIndent() 108 | 109 | settingsFile = rootProjectDir.newFile('settings.gradle') 110 | settingsFile << ''' 111 | include 'libraryProject', 'vaadinProject' 112 | '''.stripIndent() 113 | 114 | testStart = System.currentTimeMillis() 115 | println "Running test in ${rootProjectDir.root}" 116 | println "Using Yarn cache dir $offlineCachePath" 117 | } 118 | 119 | /** 120 | * Cleans up the test 121 | */ 122 | protected void cleanup() { 123 | long ms = System.currentTimeMillis() - testStart 124 | println "Test took ${TimeUnit.MILLISECONDS.toSeconds(ms)} seconds." 125 | } 126 | 127 | /** 128 | * Runs the project 129 | * 130 | * @param args 131 | * the command line arguments to pass to gradle 132 | * @return 133 | * the result of the build 134 | */ 135 | protected BuildResult run(File projectDir=rootProjectDir.root, ConfigureRunner config = { }, String... args) { 136 | 137 | GradleRunner runner = GradleRunner.create() 138 | .withProjectDir(projectDir) 139 | .withArguments(['--stacktrace', '--info'] + (args as List)) 140 | .withPluginClasspath() 141 | 142 | config.run(runner) 143 | println "Running gradle ${runner.arguments.join(' ')}" 144 | runner.build() 145 | } 146 | 147 | /** 148 | * Runs the project and is expected to fail 149 | * 150 | * @param args 151 | * the command line arguments to pass to gradle 152 | * @return 153 | * the result of the build 154 | */ 155 | protected BuildResult runAndFail(File projectDir=rootProjectDir.root, 156 | ConfigureRunner config = { }, String... args) { 157 | GradleRunner runner = GradleRunner.create() 158 | .withProjectDir(projectDir) 159 | .withArguments(['--stacktrace', '--info'] + (args as List)) 160 | .withPluginClasspath() 161 | config.run(runner) 162 | println "Running gradle ${runner.arguments.join(' ')}" 163 | runner.buildAndFail() 164 | } 165 | 166 | /** 167 | * Interface representing a GradleRunner configuration closure 168 | */ 169 | @FunctionalInterface 170 | interface ConfigureRunner { 171 | void run(GradleRunner runner) 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/functionalTest/groovy/com/devsoap/vaadinflow/WarArchiveTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import com.devsoap.vaadinflow.tasks.CreateProjectTask 21 | import org.gradle.testkit.runner.BuildResult 22 | import org.gradle.testkit.runner.TaskOutcome 23 | 24 | import java.nio.file.Paths 25 | import java.util.zip.ZipEntry 26 | import java.util.zip.ZipFile 27 | 28 | /** 29 | * War packaging tess 30 | * 31 | * @author John Ahlroos 32 | * @since 1.0 33 | */ 34 | class WarArchiveTest extends FunctionalTest { 35 | 36 | void 'Wrapped CSS styles are packaged into WAR'() { 37 | setup: 38 | extraPlugins = ['war':''] 39 | buildFile << ''' 40 | vaadin.autoconfigure() 41 | '''.stripIndent() 42 | when: 43 | run CreateProjectTask.NAME 44 | BuildResult result = run 'war' 45 | List files = getFilesInFolder('frontend/styles') 46 | then: 47 | result.task(':war').outcome == TaskOutcome.SUCCESS 48 | files.size() == 2 49 | files[0].name == "frontend/styles/${testProjectDir.root.name}-theme.css" 50 | files[1].name == "frontend/styles/${testProjectDir.root.name}-theme.html" 51 | } 52 | 53 | void 'Styles are included when using custom webapp directory'() { 54 | setup: 55 | extraPlugins = ['war':''] 56 | buildFile << ''' 57 | vaadinAssembleClient { 58 | webappDir 'src' 59 | } 60 | vaadin.autoconfigure() 61 | '''.stripIndent() 62 | when: 63 | run CreateProjectTask.NAME 64 | BuildResult result = run 'war' 65 | List files = getFilesInFolder('frontend/styles') 66 | then: 67 | result.task(':war').outcome == TaskOutcome.SUCCESS 68 | files.size() == 2 69 | files[0].name == "frontend/styles/${testProjectDir.root.name}-theme.css" 70 | files[1].name == "frontend/styles/${testProjectDir.root.name}-theme.html" 71 | } 72 | 73 | private ZipFile getWarFile() { 74 | File libsDir = Paths.get(testProjectDir.root.canonicalPath, 'build', 'libs').toFile() 75 | new ZipFile(new File(libsDir, testProjectDir.root.name + '.war')) 76 | } 77 | 78 | private List getFilesInFolder(String folder) { 79 | warFile.entries() 80 | .findAll { ZipEntry entry -> !entry.directory && entry.name.startsWith(folder) } 81 | .sort { ZipEntry a, ZipEntry b -> a.name <=> b.name } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/functionalTest/resources/AllTestsConfig.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | import com.devsoap.vaadinflow.FunctionalTest 19 | import com.devsoap.vaadinflow.MultimoduleFunctionalTest 20 | 21 | runner { 22 | include FunctionalTest, MultimoduleFunctionalTest 23 | } 24 | -------------------------------------------------------------------------------- /src/functionalTest/resources/ClientDependenciesTestsConfig.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import com.devsoap.vaadinflow.ClientDependenciesTest 20 | import com.devsoap.vaadinflow.LegacyClientDependenciesTest 21 | 22 | runner { 23 | include LegacyClientDependenciesTest, ClientDependenciesTest 24 | } 25 | -------------------------------------------------------------------------------- /src/functionalTest/resources/ClientProductionModeConfigTestsConfig.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | import com.devsoap.vaadinflow.LegacyClientProductionModeConfigTest 19 | 20 | runner { 21 | include LegacyClientProductionModeConfigTest 22 | } 23 | -------------------------------------------------------------------------------- /src/functionalTest/resources/ClientProductionModeTestsConfig.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import com.devsoap.vaadinflow.LegacyClientProductionModeTest 20 | 21 | runner { 22 | include LegacyClientProductionModeTest 23 | } 24 | -------------------------------------------------------------------------------- /src/functionalTest/resources/SmokeTestsConfig.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | import com.devsoap.spock.Smoke 19 | 20 | runner { 21 | include Smoke 22 | } 23 | -------------------------------------------------------------------------------- /src/functionalTest/resources/UncategorizedTestsConfig.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | import com.devsoap.spock.Smoke 19 | import com.devsoap.vaadinflow.ClientDependenciesTest 20 | import com.devsoap.vaadinflow.LegacyClientDependenciesTest 21 | import com.devsoap.vaadinflow.LegacyClientProductionModeConfigTest 22 | import com.devsoap.vaadinflow.LegacyClientProductionModeTest 23 | import com.devsoap.vaadinflow.FunctionalTest 24 | import com.devsoap.vaadinflow.MultimoduleFunctionalTest 25 | 26 | runner { 27 | include FunctionalTest, MultimoduleFunctionalTest 28 | exclude LegacyClientDependenciesTest, LegacyClientProductionModeTest, LegacyClientProductionModeConfigTest, 29 | ClientDependenciesTest, Smoke 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/NodePlugin.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow 19 | 20 | import com.devsoap.vaadinflow.tasks.NodeSetupTask 21 | import com.moowork.gradle.node.NodeExtension 22 | import com.moowork.gradle.node.npm.NpmInstallTask 23 | import com.moowork.gradle.node.npm.NpmSetupTask 24 | import com.moowork.gradle.node.npm.NpmTask 25 | import com.moowork.gradle.node.task.NodeTask 26 | import com.moowork.gradle.node.variant.VariantBuilder 27 | import com.moowork.gradle.node.yarn.YarnInstallTask 28 | import com.moowork.gradle.node.yarn.YarnSetupTask 29 | import com.moowork.gradle.node.yarn.YarnTask 30 | import groovy.transform.Internal 31 | import org.gradle.api.Plugin 32 | import org.gradle.api.Project 33 | 34 | /** 35 | * A modified version of com.moowork.gradle.node.NodePlugin to fix Gradle 6 issues 36 | * 37 | * Note: This class is internal and might be removed if the upstream plugin is updated. Do not rely on this 38 | * class to exist. 39 | * 40 | * @author John Ahlroos 41 | * @since 1.1 42 | */ 43 | @Internal 44 | class NodePlugin implements Plugin { 45 | 46 | private Project project 47 | private NodeExtension config 48 | private NodeSetupTask setupTask 49 | private NpmSetupTask npmSetupTask 50 | private YarnSetupTask yarnSetupTask 51 | 52 | @Override 53 | void apply( final Project project ) { 54 | this.project = project 55 | this.config = NodeExtension.create( this.project ) 56 | addGlobalTypes() 57 | addTasks() 58 | project.afterEvaluate { 59 | this.config.variant = new VariantBuilder( this.config ).build() 60 | configureSetupTask() 61 | configureNpmSetupTask() 62 | configureYarnSetupTask() 63 | } 64 | } 65 | 66 | private void addGlobalTypes() { 67 | addGlobalTaskType( NodeTask ) 68 | addGlobalTaskType( NpmTask ) 69 | addGlobalTaskType( YarnTask ) 70 | } 71 | 72 | private void addTasks() { 73 | this.project.tasks.create( NpmInstallTask.NAME, YarnInstallTask ) 74 | this.project.tasks.create( YarnInstallTask.NAME, YarnInstallTask ) 75 | this.setupTask = this.project.tasks.create( NodeSetupTask.NAME, NodeSetupTask ) 76 | this.npmSetupTask = this.project.tasks.create( NpmSetupTask.NAME, NpmSetupTask ) 77 | this.yarnSetupTask = this.project.tasks.create( YarnSetupTask.NAME, YarnSetupTask ) 78 | } 79 | 80 | private void addGlobalTaskType( Class type ) { 81 | project.extensions.extraProperties.set( type.simpleName, type ) 82 | } 83 | 84 | private void configureSetupTask() { 85 | setupTask.setEnabled( config.download ) 86 | } 87 | 88 | private void configureNpmSetupTask() { 89 | npmSetupTask.configureVersion( config.npmVersion ) 90 | } 91 | 92 | private void configureYarnSetupTask() { 93 | yarnSetupTask.configureVersion( config.yarnVersion ) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/GrettyDeprecatedPluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import org.gradle.api.Project 21 | 22 | /** 23 | * Deprecated old Gretty Plugin 24 | * 25 | * @author John Ahlroos 26 | * @since 1.0 27 | */ 28 | class GrettyDeprecatedPluginAction extends PluginAction { 29 | 30 | final String pluginId = 'org.akhikhl.gretty' 31 | 32 | @Override 33 | protected void execute(Project project) { 34 | throw new IllegalArgumentException('The Gretty plugin used in this project is deprecated and un-maintained ' + 35 | '(See https://github.com/akhikhl/gretty/issues/436). ' + 36 | 'Replace it with the \'org.gretty\' plugin instead.') 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/JavaPluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import org.gradle.api.Project 21 | import org.gradle.api.plugins.JavaPluginConvention 22 | 23 | /** 24 | * Configures the Java plugin 25 | * 26 | * @author John Ahlroos 27 | * @since 1.3 28 | */ 29 | class JavaPluginAction extends PluginAction { 30 | 31 | final String pluginId = 'java' 32 | 33 | static final String JAVASCRIPT_SOURCES = 'src/main/javascript' 34 | static final String STYLESHEETS_SOURCES = 'src/main/stylesheets' 35 | 36 | @Override 37 | protected void execute(Project project) { 38 | super.execute(project) 39 | JavaPluginConvention javaPlugin = project.convention.getPlugin(JavaPluginConvention) 40 | javaPlugin.sourceSets.main.resources.with { 41 | if (project.file(JAVASCRIPT_SOURCES).exists()) { 42 | srcDir(JAVASCRIPT_SOURCES) 43 | } 44 | if (project.file(STYLESHEETS_SOURCES).exists()) { 45 | srcDir(STYLESHEETS_SOURCES) 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/NodePluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import com.devsoap.vaadinflow.NodePlugin 21 | import com.devsoap.vaadinflow.extensions.VaadinClientDependenciesExtension 22 | import com.devsoap.vaadinflow.util.HttpUtils 23 | import com.devsoap.vaadinflow.util.LogUtils 24 | import com.devsoap.vaadinflow.util.TemplateWriter 25 | import com.devsoap.vaadinflow.util.Versions 26 | import com.moowork.gradle.node.NodeExtension 27 | import com.moowork.gradle.node.npm.NpmSetupTask 28 | import com.moowork.gradle.node.yarn.YarnSetupTask 29 | import groovy.util.logging.Log 30 | import org.apache.tools.ant.taskdefs.condition.Os 31 | import org.gradle.api.Project 32 | import org.gradle.api.artifacts.Dependency 33 | import org.gradle.process.ExecSpec 34 | 35 | import java.util.logging.Level 36 | 37 | /** 38 | * Action taken when the Node plugin is applied to a project 39 | * 40 | * @author John Ahlroos 41 | * @since 1.0 42 | */ 43 | @Log('LOGGER') 44 | class NodePluginAction extends PluginAction { 45 | 46 | final String pluginId = 'com.moowork.node' 47 | 48 | private static final String NPM_RC_FILENAME = '.npmrc' 49 | 50 | @Override 51 | void apply(Project project) { 52 | this.project = project 53 | project.with { 54 | 55 | // Can't use super.apply() as it uses plugins.withId() which will return the mooworks plugin 56 | plugins.withType(NodePlugin) { 57 | project.gradle.taskGraph.removeTaskExecutionListener(taskListener) 58 | project.gradle.taskGraph.addTaskExecutionListener(taskListener) 59 | project.gradle.projectsEvaluated { 60 | executeAfterAllEvaluations() 61 | } 62 | execute(project) 63 | project.afterEvaluate { 64 | executeAfterEvaluate(project) 65 | } 66 | } 67 | 68 | pluginManager.apply(NodePlugin) 69 | 70 | String nodeDependnecy = 71 | "com.moowork.gradle:gradle-node-plugin:${Versions.rawVersion('node.plugin.version')}" 72 | Dependency node = dependencies.create(nodeDependnecy) { 73 | description = 'Node Gradle Plugin' 74 | } 75 | configurations['compileOnly'].dependencies.add(node) 76 | } 77 | } 78 | 79 | @Override 80 | protected void execute(Project project) { 81 | super.execute(project) 82 | 83 | LOGGER.info('Configuring node extension for vaadin project') 84 | NodeExtension nodeExtension = project.extensions.getByType(NodeExtension) 85 | nodeExtension.download = true 86 | nodeExtension.nodeModulesDir = project.file(VaadinClientDependenciesExtension.FRONTEND_BUILD_DIR) 87 | nodeExtension.npmVersion = Versions.rawVersion('npm.version') 88 | nodeExtension.yarnVersion = 89 | Versions.rawVersion(Os.isFamily(Os.FAMILY_WINDOWS) ? 'windows.yarn.version' : 'yarn.version') 90 | nodeExtension.version = 91 | Versions.rawVersion(Os.isFamily(Os.FAMILY_WINDOWS) ? 'windows.node.version' : 'node.version') 92 | } 93 | 94 | @Override 95 | protected void executeAfterEvaluate(Project project) { 96 | super.executeAfterEvaluate(project) 97 | 98 | File frontend = new File(project.buildDir, 'frontend') 99 | if (!frontend.exists()) { 100 | frontend.mkdirs() 101 | } 102 | File npmrc = new File(frontend, NPM_RC_FILENAME) 103 | if (!npmrc.exists()) { 104 | Map params = [:] 105 | params['update-notifier'] = false 106 | 107 | if (HttpUtils.httpsProxy) { 108 | params['https-proxy'] = HttpUtils.httpsProxy 109 | } 110 | 111 | if (HttpUtils.httpProxy) { 112 | params['proxy'] = HttpUtils.httpProxy 113 | } 114 | 115 | VaadinClientDependenciesExtension vaadinClient = project.extensions 116 | .getByType(VaadinClientDependenciesExtension) 117 | params.putAll(vaadinClient.customNpmProperties) 118 | 119 | TemplateWriter.builder() 120 | .targetDir(frontend) 121 | .templateFileName(NPM_RC_FILENAME) 122 | .substitutions(['parameters' : params]) 123 | .build().write() 124 | } 125 | 126 | YarnSetupTask yarnSetup = project.tasks.getByName(YarnSetupTask.NAME) 127 | yarnSetup.args.add(2, '--userconfig') 128 | yarnSetup.args.add(3, npmrc.canonicalPath) 129 | yarnSetup.execOverrides = { ExecSpec spec -> 130 | spec.standardOutput = LogUtils.getLogOutputStream(Level.INFO) 131 | spec.errorOutput = LogUtils.getLogOutputStream(Level.INFO) 132 | } 133 | 134 | NpmSetupTask npmSetup = project.tasks.getByName(NpmSetupTask.NAME) 135 | npmSetup.execOverrides = { ExecSpec spec -> 136 | spec.standardOutput = LogUtils.getLogOutputStream(Level.INFO) 137 | spec.errorOutput = LogUtils.getLogOutputStream(Level.INFO) 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/PluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import com.devsoap.vaadinflow.VaadinFlowPlugin 21 | import org.gradle.api.Project 22 | import org.gradle.api.Task 23 | import org.gradle.api.execution.TaskExecutionListener 24 | import org.gradle.api.plugins.PluginManager 25 | import org.gradle.api.tasks.Internal 26 | import org.gradle.api.tasks.TaskState 27 | 28 | /** 29 | * Base class for reacting to other plugins 30 | * 31 | * @author John Ahlroos 32 | * @since 1.0 33 | */ 34 | abstract class PluginAction { 35 | 36 | private final TaskListener taskListener = new TaskListener() 37 | 38 | protected Project project 39 | 40 | /** 41 | * The unique identifer for the plugin 42 | */ 43 | abstract String getPluginId() 44 | 45 | /** 46 | * Executes the defined action when then Gradle Vaadin plugin is applied. This is only called 47 | * if the user has applied the plugin id for this plugin action. 48 | * 49 | * @param project 50 | * the project to apply the action to 51 | */ 52 | protected void execute(Project project) { 53 | project.logger.info("Applying ${getClass().simpleName} actions to project $project.name") 54 | } 55 | 56 | /** 57 | * This is called after project evaluation. 58 | * 59 | * @param project 60 | * the project which was evaluated 61 | */ 62 | protected void executeAfterEvaluate(Project project) { 63 | project.logger.debug("Executing afterEvaluate hook for ${getClass().simpleName}") 64 | } 65 | 66 | /** 67 | * This is called after all projects have been evaluated 68 | */ 69 | protected void executeAfterAllEvaluations() { 70 | project.logger.debug("Executing afterAllEvaulations hook for ${getClass().simpleName}") 71 | } 72 | 73 | /** 74 | * Called before a task is executed. This is only called if the user has applied the plugin id for 75 | * this plugin action. 76 | * 77 | * @param task 78 | * task that will be executed 79 | */ 80 | protected void beforeTaskExecuted(Task task) { 81 | task.project.logger.debug("Executing pre task hook for ${getClass().simpleName} for task $task.name") 82 | } 83 | 84 | /** 85 | * Called after a task has executed. This is only called if the user has applied the plugin id for 86 | * this plugin action. 87 | * 88 | * @param task 89 | * task that was executed 90 | */ 91 | protected void afterTaskExecuted(Task task) { 92 | task.project.logger.debug("Executing post task hook for ${getClass().simpleName} for task $task.name") 93 | } 94 | 95 | /** 96 | * Applies the plugin action to a project. 97 | * 98 | * Please note that by applying the action to a project only adds the support for the action to the project. You 99 | * also have to apply the plugin id the action is for to execute action. 100 | * 101 | * @param project 102 | * the project to apply the plugin action to 103 | */ 104 | void apply(Project project) { 105 | this.project = project 106 | project.plugins.withId(pluginId) { 107 | project.gradle.taskGraph.removeTaskExecutionListener(taskListener) 108 | project.gradle.taskGraph.addTaskExecutionListener(taskListener) 109 | project.gradle.projectsEvaluated { 110 | executeAfterAllEvaluations() 111 | } 112 | execute(project) 113 | project.afterEvaluate { 114 | executeAfterEvaluate(project) 115 | } 116 | } 117 | } 118 | 119 | /** 120 | * Returns the internal tasklistener 121 | */ 122 | @Internal 123 | protected TaskListener getTaskListener() { 124 | taskListener 125 | } 126 | 127 | /** 128 | * Is the task applicable for the project. The task is applicable iff the Gradle Vaadin plugin is applied to the 129 | * project. 130 | * 131 | * @param task 132 | * the task to check. 133 | * 134 | * @return 135 | * true if the task is applicable to the project. 136 | */ 137 | final static boolean isApplicable(Task task) { 138 | PluginManager pluginManager = task.project.pluginManager 139 | pluginManager.hasPlugin(VaadinFlowPlugin.PLUGIN_ID) 140 | } 141 | 142 | private final class TaskListener implements TaskExecutionListener { 143 | 144 | @Override 145 | void beforeExecute(Task task) { 146 | if (isApplicable(task) ) { 147 | beforeTaskExecuted(task) 148 | } 149 | } 150 | 151 | @Override 152 | void afterExecute(Task task, TaskState state) { 153 | if (isApplicable(task) && state.executed) { 154 | afterTaskExecuted(task) 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/SassJavaPluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import com.devsoap.vaadinflow.tasks.WrapCssTask 21 | import org.gradle.api.Project 22 | import org.gradle.api.Task 23 | 24 | /** 25 | * Integrate JSASS Java plugin 26 | * 27 | * @author John Ahlroos 28 | * @since 1.1 29 | */ 30 | class SassJavaPluginAction extends PluginAction { 31 | 32 | final String pluginId = 'io.freefair.jsass-java' 33 | 34 | @Override 35 | protected void executeAfterEvaluate(Project project) { 36 | super.executeAfterEvaluate(project) 37 | WrapCssTask convertCss = project.tasks.getByName(WrapCssTask.NAME) 38 | 39 | Task compileSass = project.tasks.getByName('compileSass') 40 | convertCss.dependsOn(compileSass) 41 | convertCss.inputs.files(compileSass.outputs.files) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/SassWarPluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import com.devsoap.vaadinflow.tasks.WrapCssTask 21 | import org.gradle.api.Project 22 | import org.gradle.api.Task 23 | 24 | /** 25 | * Integrate JSASS Java plugin 26 | * 27 | * @author John Ahlroos 28 | * @since 1.1 29 | */ 30 | class SassWarPluginAction extends PluginAction { 31 | 32 | final String pluginId = 'io.freefair.jsass-war' 33 | 34 | @Override 35 | protected void executeAfterEvaluate(Project project) { 36 | super.executeAfterEvaluate(project) 37 | WrapCssTask convertCss = project.tasks.getByName(WrapCssTask.NAME) 38 | 39 | Task compileSass = project.tasks.getByName('compileWebappSass') 40 | convertCss.dependsOn(compileSass) 41 | convertCss.inputs.files(compileSass.outputs.files) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/SpringBootAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 21 | import com.devsoap.vaadinflow.tasks.AssembleClientDependenciesTask 22 | import com.devsoap.vaadinflow.util.PackagingUtil 23 | import org.gradle.api.GradleException 24 | import org.gradle.api.Project 25 | import org.gradle.api.Task 26 | import org.gradle.api.plugins.JavaPluginConvention 27 | import org.gradle.api.tasks.JavaExec 28 | import org.gradle.api.tasks.SourceSet 29 | import org.gradle.api.tasks.bundling.Jar 30 | import org.gradle.api.tasks.bundling.War 31 | 32 | import java.nio.file.Paths 33 | 34 | /** 35 | * Configures the Spring Boot plugin to support the Vaadin resources 36 | * 37 | * @author John Ahlroos 38 | * @since 1.0 39 | */ 40 | class SpringBootAction extends PluginAction { 41 | 42 | final String pluginId = 'org.springframework.boot' 43 | 44 | private static final String BOOT_RUN_TASK = 'bootRun' 45 | 46 | private static final String BOOT_JAR_TASK = 'bootJar' 47 | private static final String BOOT_WAR_TASK = 'bootWar' 48 | 49 | private static final String WEBAPP_GEN = 'webapp-gen' 50 | private static final String SPRING_BOOT_RESOURCES_PATH = 'META-INF/resources' 51 | 52 | /** 53 | * Is Spring Boot plugin active for the project 54 | * 55 | * @param project 56 | * the project to check 57 | * @return 58 | * true if active 59 | */ 60 | static boolean isActive(Project project) { 61 | project.plugins.hasPlugin(new SpringBootAction().pluginId) 62 | } 63 | 64 | @Override 65 | protected void execute(Project project) { 66 | super.execute(project) 67 | 68 | // Configure tasks 69 | project.tasks.with { 70 | findByName(BOOT_JAR_TASK)?.dependsOn(AssembleClientDependenciesTask.NAME) 71 | findByName(BOOT_WAR_TASK)?.dependsOn(AssembleClientDependenciesTask.NAME) 72 | findByName(BOOT_RUN_TASK)?.with { 73 | dependsOn(AssembleClientDependenciesTask.NAME) 74 | JavaPluginConvention javaPlugin = project.convention.getPlugin(JavaPluginConvention) 75 | SourceSet mainSourceSet = javaPlugin.sourceSets.main 76 | it.sourceResources(mainSourceSet) 77 | } 78 | } 79 | } 80 | 81 | @Override 82 | protected void executeAfterEvaluate(Project project) { 83 | super.executeAfterEvaluate(project) 84 | 85 | AssembleClientDependenciesTask assembleTask = project.tasks.findByName(AssembleClientDependenciesTask.NAME) 86 | JavaPluginConvention javaPlugin = project.convention.getPlugin(JavaPluginConvention) 87 | SourceSet mainSourceSet = javaPlugin.sourceSets.main 88 | mainSourceSet.resources.srcDir(assembleTask.webappDir) 89 | 90 | File webappGen = Paths.get(project.buildDir.canonicalPath, WEBAPP_GEN).toFile() 91 | mainSourceSet.resources.srcDir(webappGen) 92 | } 93 | 94 | @Override 95 | protected void beforeTaskExecuted(Task task) { 96 | super.beforeTaskExecuted(task) 97 | switch (task.name) { 98 | case BOOT_RUN_TASK: 99 | configureBootRun(task) 100 | break 101 | case BOOT_JAR_TASK: 102 | PackagingUtil.includeResourcesInJar((Jar) task, SPRING_BOOT_RESOURCES_PATH) 103 | break 104 | case BOOT_WAR_TASK: 105 | configureBootWar(task) 106 | break 107 | } 108 | } 109 | 110 | private static void configureBootRun(Task task) { 111 | JavaExec bootRun = (JavaExec) task 112 | VaadinFlowPluginExtension vaadin = task.project.extensions.getByType(VaadinFlowPluginExtension) 113 | bootRun.systemProperties = bootRun.systemProperties ?: [:] 114 | bootRun.systemProperties.putIfAbsent 'vaadin.productionMode', vaadin.productionMode 115 | bootRun.systemProperties.putIfAbsent 'vaadin.compatibilityMode', vaadin.compatibilityMode 116 | bootRun.systemProperties.put 'vaadin.enableDevServer', false 117 | bootRun.classpath = task.project.files('build/webapp-gen') + bootRun.classpath 118 | 119 | if (vaadin.compatibilityMode && vaadin.productionMode) { 120 | // TODO Resolve if supporting production mode is even possible with bootRun 121 | throw new GradleException('Production mode is not supported with bootRun. ' + 122 | 'Instead package with bootJar or bootWar and execute them directly.') 123 | } 124 | } 125 | 126 | private static void configureBootWar(Task task) { 127 | War war = (War) task 128 | war.from(new File(task.project.buildDir, WEBAPP_GEN)) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/VaadinFlowPluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import static com.devsoap.license.DevsoapLicenseExtension.Credential 21 | 22 | import com.devsoap.license.DevsoapLicenseExtension 23 | import com.devsoap.license.DevsoapLicensePlugin 24 | import com.devsoap.vaadinflow.VaadinFlowPlugin 25 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 26 | import com.devsoap.vaadinflow.tasks.AssembleClientDependenciesTask 27 | import com.devsoap.vaadinflow.tasks.ConvertGroovyTemplatesToHTML 28 | import com.devsoap.vaadinflow.tasks.InstallBowerDependenciesTask 29 | import com.devsoap.vaadinflow.tasks.InstallYarnDependenciesTask 30 | import com.devsoap.vaadinflow.tasks.VersionCheckTask 31 | import com.devsoap.vaadinflow.util.LogUtils 32 | import com.devsoap.vaadinflow.util.Versions 33 | import com.devsoap.vaadinflow.util.WebJarHelper 34 | import groovy.util.logging.Log 35 | import org.gradle.api.Project 36 | import org.gradle.api.artifacts.Dependency 37 | import org.gradle.api.internal.artifacts.BaseRepositoryFactory 38 | 39 | /** 40 | * Action taken when the Vaadin plugin is applied to a project 41 | * 42 | * @author John Ahlroos 43 | * @since 1.0 44 | */ 45 | @Log('LOGGER') 46 | class VaadinFlowPluginAction extends PluginAction { 47 | 48 | final String pluginId = VaadinFlowPlugin.PLUGIN_ID 49 | 50 | private static final String PLUGIN_VERSION_KEY = 'vaadin.plugin.version' 51 | private static final String PROCESS_RESOURCES = 'processResources' 52 | private static final String RUNNING_IN_COMPATIBILITY_MODE_MESSAGE = 53 | 'The project will be compiled for Vaadin 13 (Flow 1) compatibility mode. ' 54 | private static final String COMPILE_ONLY = 'compileOnly' 55 | 56 | @Override 57 | void apply(Project project) { 58 | super.apply(project) 59 | project.plugins.apply('java') 60 | 61 | project.pluginManager.apply(DevsoapLicensePlugin) 62 | 63 | DevsoapLicenseExtension devsoap = project.extensions.getByType(DevsoapLicenseExtension) 64 | devsoap.credential(VaadinFlowPlugin.PRODUCT_NAME, 65 | System.getProperty('devsoap.gradle-flow-plugin.license.email'), 66 | System.getProperty('devsoap.gradle-flow-plugin.license.key') 67 | ) { Credential c -> 68 | c.signature = Versions.rawVersion('vaadin.plugin.signature') 69 | } 70 | 71 | String licenseDependency = 72 | "com.devsoap:devsoap-license-plugin:${ Versions.rawVersion('devsoap.license.version') }" 73 | Dependency license = project.dependencies.create(licenseDependency) 74 | project.configurations[COMPILE_ONLY].dependencies.add(license) 75 | } 76 | 77 | @Override 78 | protected void execute(Project project) { 79 | super.execute(project) 80 | project.with { 81 | tasks[PROCESS_RESOURCES].with { 82 | dependsOn(VersionCheckTask.NAME) 83 | dependsOn(ConvertGroovyTemplatesToHTML.NAME) 84 | } 85 | 86 | tasks['jar'].dependsOn(AssembleClientDependenciesTask.NAME) 87 | 88 | repositories.maven { repository -> 89 | repository.name = 'Gradle Plugin Portal' 90 | repository.url = ( 91 | System.getProperty(BaseRepositoryFactory.PLUGIN_PORTAL_OVERRIDE_URL_PROPERTY) ?: 92 | BaseRepositoryFactory.PLUGIN_PORTAL_DEFAULT_URL 93 | ) 94 | } 95 | 96 | String pluginDependency = 97 | "com.devsoap:gradle-vaadin-flow-plugin:${Versions.rawVersion(PLUGIN_VERSION_KEY)}" 98 | Dependency vaadin = dependencies.create(pluginDependency) { 99 | description = 'Gradle Vaadin Plugin' 100 | } 101 | configurations[COMPILE_ONLY].dependencies.add(vaadin) 102 | } 103 | } 104 | 105 | @Override 106 | protected void executeAfterAllEvaluations() { 107 | super.executeAfterAllEvaluations() 108 | WebJarHelper.findDependantJarTasks(project).each { 109 | project.tasks[InstallYarnDependenciesTask.NAME].dependsOn(it) 110 | project.tasks[InstallBowerDependenciesTask.NAME].dependsOn(it) 111 | } 112 | } 113 | 114 | @Override 115 | protected void executeAfterEvaluate(Project project) { 116 | super.executeAfterEvaluate(project) 117 | 118 | String vaadinVersion = Versions.version(PLUGIN_VERSION_KEY) 119 | 120 | LogUtils.printIfNotPrintedBefore( project, "Using DS Gradle Vaadin Flow Plugin $vaadinVersion") 121 | 122 | VaadinFlowPluginExtension vaadin = project.extensions[VaadinFlowPluginExtension.NAME] 123 | if (!vaadin.versionSet) { 124 | LOGGER.warning('vaadin.version is not set, falling back to latest Vaadin version') 125 | } 126 | 127 | if (vaadin.compatibilityMode) { 128 | LOGGER.warning( 129 | RUNNING_IN_COMPATIBILITY_MODE_MESSAGE + 130 | 'To disable compatibility mode set vaadin.compatibilityMode=false.') 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/WarPluginAction.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.actions 19 | 20 | import com.devsoap.vaadinflow.tasks.AssembleClientDependenciesTask 21 | import org.gradle.api.Project 22 | import org.gradle.api.tasks.bundling.War 23 | 24 | import java.nio.file.Paths 25 | 26 | /** 27 | * Configures the War plugin 28 | * 29 | * @author John Ahlroos 30 | * @since 1.0 31 | */ 32 | class WarPluginAction extends PluginAction { 33 | 34 | final String pluginId = 'war' 35 | 36 | @Override 37 | protected void executeAfterEvaluate(Project project) { 38 | super.executeAfterEvaluate(project) 39 | project.tasks.withType(War) { War task -> 40 | task.from(new File(project.buildDir, 'webapp-gen')) 41 | task.from(Paths.get(project.buildDir.canonicalPath, 'resources', 'main').toFile()) 42 | AssembleClientDependenciesTask assembleTask = project.tasks.findByName(AssembleClientDependenciesTask.NAME) 43 | task.dependsOn(assembleTask) 44 | if (assembleTask.webappDirSet) { 45 | task.from(assembleTask.webappDir) 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/actions/package-info.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * Actions based on applied plugins to the project. 21 | */ 22 | package com.devsoap.vaadinflow.actions 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/creators/VaadinProjectCreator.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.creators 19 | 20 | import com.devsoap.vaadinflow.actions.JavaPluginAction 21 | import com.devsoap.vaadinflow.models.ApplicationType 22 | import com.devsoap.vaadinflow.models.VaadinProject 23 | import com.devsoap.vaadinflow.util.TemplateWriter 24 | 25 | import java.nio.file.Paths 26 | 27 | /** 28 | * Creates Vaadin projects from templates 29 | * 30 | * @author John Ahlroos 31 | * @since 1.0 32 | */ 33 | class VaadinProjectCreator { 34 | 35 | /** 36 | * Creates the source files and file structure according to the VaadinProject model and the associated file 37 | * templates 38 | * 39 | * @param vaadinProject 40 | * the project model 41 | */ 42 | void generate(VaadinProject vaadinProject) { 43 | 44 | File root = vaadinProject.rootDirectory 45 | File sourceMain = Paths.get(root.canonicalPath, 'src', 'main').toFile() 46 | 47 | File languageSourceDir = new File(sourceMain, vaadinProject.projectType.sourceDir) 48 | String sourceFileExtension = vaadinProject.projectType.extension 49 | 50 | File pkgDir = Paths.get(languageSourceDir.canonicalPath, 51 | vaadinProject.applicationPackage.split('\\.')).toFile() 52 | String appClassName = TemplateWriter.makeStringJavaCompatible(vaadinProject.applicationName) 53 | 54 | TemplateWriter.builder() 55 | .templateFileName(vaadinProject.compatibilityMode ? 56 | "AppView.$sourceFileExtension" : "AppView.v14.$sourceFileExtension") 57 | .targetDir(pkgDir) 58 | .targetFileName("${appClassName}View.$sourceFileExtension") 59 | .substitutions([ 60 | 'applicationPackage': vaadinProject.applicationPackage, 61 | 'applicationName' : appClassName, 62 | 'applicationBaseTheme' : vaadinProject.applicationBaseTheme, 63 | 'applicationTheme' : vaadinProject.applicationName.toLowerCase() + 64 | "-theme.${vaadinProject.compatibilityMode ? 'html' : 'css'}", 65 | ]).build().write() 66 | 67 | if (vaadinProject.compatibilityMode) { 68 | TemplateWriter.builder() 69 | .templateFileName("Servlet.$sourceFileExtension") 70 | .targetDir(pkgDir) 71 | .targetFileName("${appClassName}Servlet.$sourceFileExtension") 72 | .substitutions([ 73 | 'applicationPackage' : vaadinProject.applicationPackage, 74 | 'applicationName' : vaadinProject.applicationName, 75 | 'productionMode' : vaadinProject.productionMode 76 | ]).build().write() 77 | 78 | TemplateWriter.builder() 79 | .templateFileName("UI.$sourceFileExtension") 80 | .targetDir(pkgDir) 81 | .targetFileName("${appClassName}UI.$sourceFileExtension") 82 | .substitutions([ 83 | 'applicationPackage': vaadinProject.applicationPackage, 84 | 'applicationName' : appClassName, 85 | 'applicationTheme' : vaadinProject.applicationName.toLowerCase() + 86 | "-theme.${vaadinProject.compatibilityMode ? 'html' : 'css'}", 87 | 'applicationBaseTheme' : vaadinProject.applicationBaseTheme 88 | ]).build().write() 89 | } else { 90 | TemplateWriter.builder() 91 | .templateFileName('hello-button.js') 92 | .targetDir(getJavascriptDir(vaadinProject)) 93 | .substitutions([ 94 | 'applicationPackage' : vaadinProject.applicationPackage 95 | ]).build().write() 96 | 97 | TemplateWriter.builder() 98 | .templateFileName("HelloButton.$sourceFileExtension") 99 | .targetDir(pkgDir) 100 | .substitutions([ 101 | 'applicationPackage' : vaadinProject.applicationPackage 102 | ]).build().write() 103 | } 104 | 105 | if (vaadinProject.applicationType == ApplicationType.SPRING_BOOT) { 106 | TemplateWriter.builder() 107 | .templateFileName("SpringBootApplication.$sourceFileExtension") 108 | .targetDir(pkgDir) 109 | .targetFileName("${appClassName}Application.$sourceFileExtension") 110 | .substitutions([ 111 | 'applicationPackage': vaadinProject.applicationPackage, 112 | 'applicationName' : appClassName 113 | ]) 114 | .build().write() 115 | } 116 | } 117 | 118 | private static File getJavascriptDir(VaadinProject vaadinProject) { 119 | Paths.get(vaadinProject.rootDirectory.canonicalPath, 120 | JavaPluginAction.JAVASCRIPT_SOURCES.split('/')).toFile() 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/creators/VaadinThemeCreator.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.creators 19 | 20 | import com.devsoap.vaadinflow.actions.JavaPluginAction 21 | import com.devsoap.vaadinflow.models.VaadinProject 22 | import com.devsoap.vaadinflow.util.TemplateWriter 23 | import groovy.util.logging.Log 24 | 25 | import java.nio.file.Paths 26 | 27 | /** 28 | * Creates Vaadin themes 29 | * 30 | * @author John Ahlroos 31 | * @since 1.0 32 | */ 33 | @Log('LOGGER') 34 | class VaadinThemeCreator { 35 | 36 | /** 37 | * Generates a Css theme that can be included with the @StyleSheet annotation 38 | * 39 | * @param vaadinProject 40 | * the project model 41 | */ 42 | void generateCssTheme(VaadinProject vaadinProject) { 43 | String appClassName = TemplateWriter.makeStringJavaCompatible(vaadinProject.applicationName) 44 | String themeName = vaadinProject.compatibilityMode ? "${appClassName.toLowerCase()}-theme.css" : 'theme.css' 45 | TemplateWriter.builder() 46 | .templateFileName('AppTheme.css') 47 | .targetDir(getStylesDir(vaadinProject)) 48 | .targetFileName(themeName) 49 | .build().write() 50 | } 51 | 52 | private static File getStylesDir(VaadinProject vaadinProject) { 53 | vaadinProject.compatibilityMode ? 54 | Paths.get(vaadinProject.webappDirectory.canonicalPath, 55 | 'frontend', 'styles').toFile() : 56 | Paths.get(vaadinProject.rootDirectory.canonicalPath, 57 | JavaPluginAction.STYLESHEETS_SOURCES.split('/')).toFile() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/creators/package-info.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * Contains classes for generating source code from templates 21 | */ 22 | package com.devsoap.vaadinflow.creators 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/extensions/package-info.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * Contains Gradle extensions 21 | */ 22 | package com.devsoap.vaadinflow.extensions 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/ApplicationType.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | import groovy.transform.Memoized 21 | import org.gradle.api.Project 22 | 23 | /** 24 | * The type of application to generate 25 | * 26 | * @author John Ahlroos 27 | * @since 1.0 28 | */ 29 | enum ApplicationType { 30 | 31 | /** 32 | * Standard deployable web application (WAR) 33 | */ 34 | WEB_APPLICATION, 35 | 36 | /** 37 | * Spring Boot Application 38 | */ 39 | SPRING_BOOT 40 | 41 | /** 42 | * Get the application type for a project 43 | * 44 | * @param project 45 | * the project to get the type for 46 | */ 47 | static ApplicationType get(Project project) { 48 | if (project.plugins.findPlugin('org.springframework.boot')) { 49 | return SPRING_BOOT 50 | } 51 | WEB_APPLICATION 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/ClassModel.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * A model for representing a Java/Groovy/Kotlin class 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | trait ClassModel { 27 | 28 | String componentName 29 | 30 | String componentPackage 31 | 32 | ProjectType projectType 33 | } 34 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/ClientPackage.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * TemplateModel for representing a client package in bower.json 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class ClientPackage { 27 | 28 | String name 29 | 30 | String version = '1.0' 31 | 32 | String main 33 | 34 | String author 35 | 36 | String license 37 | 38 | String description 39 | 40 | List keywords 41 | 42 | Map scripts 43 | 44 | Map devDependencies 45 | 46 | Map dependencies 47 | } 48 | 49 | /** 50 | * @since 1.3.3 51 | */ 52 | class PackageJson extends ClientPackage { 53 | 54 | Map vaadin 55 | } 56 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/Component.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * TemplateModel for representing a plain Vaadin component 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class Component implements TemplateModel, ClassModel { 27 | 28 | String componentTag 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/Composite.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * TemplateModel for representing a Composite component 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class Composite implements TemplateModel, ClassModel { 27 | 28 | String componentBaseClass 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/PolymerBuild.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * TemplateModel for representing a polymer build (polymer.json) 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class PolymerBuild { 27 | 28 | String entrypoint 29 | 30 | List sources = [] 31 | 32 | List extraDependencies = [] 33 | 34 | List builds = [] 35 | 36 | /** 37 | * Represents a single build in the build process. 38 | */ 39 | interface Build { } 40 | 41 | static class CustomBuild implements Build { 42 | String name 43 | BundleConfiguration bundle = new BundleConfiguration() 44 | BuildConfiguration js = new BuildConfiguration() 45 | BuildConfiguration css = new BuildConfiguration() 46 | BuildConfiguration html = new BuildConfiguration() 47 | } 48 | 49 | /** 50 | * Represents a jss/css/html build configuration. 51 | */ 52 | static class BuildConfiguration { 53 | 54 | boolean minify = true 55 | 56 | boolean compile = false 57 | } 58 | 59 | /** 60 | * The bundle configuration 61 | */ 62 | static class BundleConfiguration { 63 | 64 | boolean rewriteUrlsInTemplates = false 65 | 66 | boolean stripComments = true 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/ProjectType.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | import com.devsoap.vaadinflow.extensions.VaadinClientDependenciesExtension 21 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 22 | import groovy.transform.Memoized 23 | import org.gradle.api.Project 24 | 25 | /** 26 | * Project language type 27 | * 28 | * @author John Ahlroos 29 | * @since 1.0 30 | */ 31 | enum ProjectType { 32 | 33 | /** 34 | * Project with Java plugin applied 35 | */ 36 | JAVA, 37 | 38 | /** 39 | * Project with Groovy plugin applied 40 | */ 41 | GROOVY, 42 | 43 | /** 44 | * Project with Kotlin plugin applied 45 | */ 46 | KOTLIN 47 | 48 | /** 49 | * Get the project type for a project 50 | * 51 | * @param project 52 | * the project to get the project type for 53 | */ 54 | static ProjectType get(Project project) { 55 | if (project.plugins.findPlugin('groovy')) { 56 | return GROOVY 57 | } else if (project.plugins.findPlugin('org.jetbrains.kotlin.jvm')) { 58 | return KOTLIN 59 | } 60 | JAVA 61 | } 62 | 63 | /** 64 | * Get the file extension of source file of this type 65 | */ 66 | String getExtension() { 67 | if (this == KOTLIN) { 68 | return 'kt' 69 | } 70 | this.name().toLowerCase() 71 | } 72 | 73 | /** 74 | * Get the source directory of this type of project 75 | */ 76 | String getSourceDir() { 77 | this.name().toLowerCase() 78 | } 79 | 80 | /** 81 | * Get the file extension for the web template 82 | */ 83 | String getTemplateExtension(boolean compatibilityMode) { 84 | if (this == GROOVY) { 85 | return 'tpl' 86 | } 87 | compatibilityMode ? 'html' : 'js' 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/TemplateModel.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * A model for generating template based files 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | trait TemplateModel { 27 | 28 | File rootDirectory 29 | 30 | File webappDirectory 31 | 32 | boolean compatibilityMode = true 33 | } 34 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/VaadinProject.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * TemplateModel for representing a Vaadin Project 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class VaadinProject implements TemplateModel { 27 | 28 | String applicationName 29 | 30 | String applicationPackage 31 | 32 | String applicationBaseTheme 33 | 34 | boolean productionMode 35 | 36 | ProjectType projectType 37 | 38 | ApplicationType applicationType 39 | } 40 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/WebComponent.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * TemplateModel for representing a Web Component 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class WebComponent extends Component { 27 | 28 | PackageManager packageManager 29 | 30 | String dependencyPackage 31 | String dependencyHtml 32 | String dependencyVersion 33 | String dependencyArtifact 34 | 35 | enum PackageManager { 36 | YARN('node_modules'), 37 | BOWER('bower_components') 38 | 39 | private final String pkg 40 | PackageManager(String pkg) { 41 | this.pkg = pkg 42 | } 43 | 44 | String getPackageDir() { 45 | pkg 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/WebTemplate.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.models 19 | 20 | /** 21 | * TemplateModel for representing a Web Template 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class WebTemplate extends Component { 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/models/package-info.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * Contains models for Vaadin projects 21 | */ 22 | package com.devsoap.vaadinflow.models 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/package-info.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * The root package for the plugin. Every class of the plugin resides under this. 21 | */ 22 | package com.devsoap.vaadinflow 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/ConvertGroovyTemplatesToHTML.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.tasks 19 | 20 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 21 | import com.devsoap.vaadinflow.models.ProjectType 22 | import groovy.text.Template 23 | import groovy.text.markup.MarkupTemplateEngine 24 | import groovy.text.markup.TemplateConfiguration 25 | import groovy.util.logging.Log 26 | import org.gradle.api.DefaultTask 27 | import org.gradle.api.file.FileTree 28 | import org.gradle.api.tasks.InputFiles 29 | import org.gradle.api.tasks.OutputDirectory 30 | import org.gradle.api.tasks.TaskAction 31 | 32 | import java.nio.file.Paths 33 | 34 | /** 35 | * TPL to HTML converter task for frontend web templates 36 | * 37 | * @author John Ahlroos 38 | * @since 1.0 39 | */ 40 | @Log('LOGGER') 41 | class ConvertGroovyTemplatesToHTML extends DefaultTask { 42 | 43 | static final String NAME = 'vaadinConvertGroovyTemplatesToHtml' 44 | 45 | static final String TEMPLATES_TARGET_PATH = 'webapp-gen/frontend/templates' 46 | 47 | @InputFiles 48 | final Closure templateFiles = { 49 | AssembleClientDependenciesTask assembleTask = project.tasks.findByName(AssembleClientDependenciesTask.NAME) 50 | File templatesPath = Paths.get(assembleTask.webappDir.canonicalPath, 'frontend', 'templates').toFile() 51 | project.fileTree(templatesPath).matching { it.include( '**/*.tpl') } 52 | } 53 | 54 | @OutputDirectory 55 | final File targetPath = new File(project.buildDir, TEMPLATES_TARGET_PATH) 56 | 57 | ConvertGroovyTemplatesToHTML() { 58 | group = 'vaadin-compatibility' 59 | description = 'Converts Groovy layout templates (tpl) into html' 60 | onlyIf { 61 | VaadinFlowPluginExtension vaadin = project.extensions.getByType(VaadinFlowPluginExtension) 62 | vaadin.compatibilityMode && ProjectType.get(project) == ProjectType.GROOVY 63 | } 64 | } 65 | 66 | @TaskAction 67 | void run() { 68 | TemplateConfiguration config = new TemplateConfiguration() 69 | MarkupTemplateEngine engine = new MarkupTemplateEngine(config) 70 | templateFiles.call().each { 71 | LOGGER.info("Converting $it.name Groovy template into HTML") 72 | targetPath.mkdirs() 73 | File htmlFile = new File(targetPath, "${ it.name - '.tpl' }.html" ) 74 | Template template = engine.createTemplate(it) 75 | Writer writer = new FileWriter(htmlFile) 76 | Writable output = template.make([:]) 77 | output.writeTo(writer) 78 | } 79 | } 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/CreateComponentTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.devsoap.vaadinflow.tasks 20 | 21 | import com.devsoap.vaadinflow.creators.ComponentCreator 22 | import com.devsoap.vaadinflow.models.Component 23 | import com.devsoap.vaadinflow.models.ProjectType 24 | 25 | import org.gradle.api.DefaultTask 26 | import org.gradle.api.tasks.Input 27 | import org.gradle.api.tasks.Optional 28 | import org.gradle.api.tasks.TaskAction 29 | import org.gradle.api.tasks.options.Option 30 | 31 | /** 32 | * Creates a new Vaadin Component 33 | * 34 | * @author John Ahlroos 35 | * @since 1.0 36 | */ 37 | class CreateComponentTask extends DefaultTask { 38 | 39 | static final String NAME = 'vaadinCreateComponent' 40 | 41 | @Input 42 | @Optional 43 | @Option(option = 'name', description = 'Component name') 44 | String componentName 45 | 46 | @Input 47 | @Optional 48 | @Option(option = 'package', description = 'Component package') 49 | String componentPackage 50 | 51 | @Input 52 | @Optional 53 | @Option(option = 'tag', description = 'Component tag') 54 | String componentTag 55 | 56 | private final ComponentCreator componentCreator = new ComponentCreator() 57 | 58 | CreateComponentTask() { 59 | description = 'Creates a new Vaadin component' 60 | group = 'Vaadin' 61 | } 62 | 63 | @TaskAction 64 | void run() { 65 | componentName = componentName ?: 'ExampleTextField' 66 | componentPackage = componentPackage ?: 'com.example.' + project.name.toLowerCase() 67 | componentTag = componentTag ?: 'input' 68 | 69 | componentCreator.generate new Component( 70 | rootDirectory : project.projectDir, 71 | componentPackage : this.componentPackage, 72 | componentName : this.componentName, 73 | componentTag : componentTag, 74 | projectType: ProjectType.get(project) 75 | ) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/CreateCompositeTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.devsoap.vaadinflow.tasks 20 | 21 | import com.devsoap.vaadinflow.creators.ComponentCreator 22 | import com.devsoap.vaadinflow.models.Composite 23 | import com.devsoap.vaadinflow.models.ProjectType 24 | import org.gradle.api.DefaultTask 25 | import org.gradle.api.tasks.Input 26 | import org.gradle.api.tasks.Optional 27 | import org.gradle.api.tasks.TaskAction 28 | import org.gradle.api.tasks.options.Option 29 | 30 | /** 31 | * Creates a new Composite Component 32 | * 33 | * Usage: 34 | * 35 | * vaadinCreateWebComponent --dependency 'bower:paper-slider:v2.0.5' 36 | * 37 | * 38 | * @author John Ahlroos 39 | * @since 1.0 40 | */ 41 | class CreateCompositeTask extends DefaultTask { 42 | 43 | static final String NAME = 'vaadinCreateComposite' 44 | 45 | @Input 46 | @Optional 47 | @Option(option = 'name', description = 'Component name') 48 | String componentName 49 | 50 | @Input 51 | @Optional 52 | @Option(option = 'package', description = 'Component package') 53 | String componentPackage 54 | 55 | @Input 56 | @Optional 57 | @Option(option = 'baseClass', description = 'Component base class') 58 | String baseClass 59 | 60 | private final ComponentCreator compositeCreator = new ComponentCreator() 61 | 62 | CreateCompositeTask() { 63 | description = 'Creates a new Vaadin web component' 64 | group = 'Vaadin' 65 | } 66 | 67 | @TaskAction 68 | void run() { 69 | componentName = componentName ?: 'ExampleComposite' 70 | componentPackage = componentPackage ?: 'com.example.' + project.name.toLowerCase() 71 | baseClass = baseClass ?: 'com.vaadin.flow.component.html.Div' 72 | 73 | compositeCreator.generate new Composite( 74 | rootDirectory: project.projectDir, 75 | componentBaseClass: baseClass, 76 | componentPackage: componentPackage, 77 | componentName: componentName, 78 | projectType: ProjectType.get(project) 79 | ) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/CreateProjectTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.tasks 19 | 20 | import com.devsoap.vaadinflow.actions.JavaPluginAction 21 | import com.devsoap.vaadinflow.models.ApplicationType 22 | import com.devsoap.vaadinflow.creators.VaadinProjectCreator 23 | import com.devsoap.vaadinflow.creators.VaadinThemeCreator 24 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 25 | import com.devsoap.vaadinflow.models.ProjectType 26 | import com.devsoap.vaadinflow.models.VaadinProject 27 | 28 | import org.gradle.api.DefaultTask 29 | import org.gradle.api.GradleException 30 | import org.gradle.api.tasks.Input 31 | import org.gradle.api.tasks.Optional 32 | import org.gradle.api.tasks.TaskAction 33 | import org.gradle.api.tasks.options.Option 34 | 35 | import java.nio.file.Paths 36 | 37 | /** 38 | * Creates a new project using a template 39 | * 40 | * @author John Ahlroos 41 | * @since 1.0 42 | */ 43 | class CreateProjectTask extends DefaultTask { 44 | 45 | static final String NAME = 'vaadinCreateProject' 46 | 47 | private static final String LUMO = 'lumo' 48 | 49 | @Input 50 | @Optional 51 | @Option(option = 'name', description = 'Application name') 52 | String applicationName 53 | 54 | @Input 55 | @Optional 56 | @Option(option = 'package', description = 'Application UI package') 57 | String applicationPackage 58 | 59 | @Input 60 | @Optional 61 | @Option(option = 'baseTheme', description = "The base theme of the application, can be either 'lumo' or 'material'") 62 | String applicationBaseTheme 63 | 64 | private final VaadinProjectCreator projectCreator = new VaadinProjectCreator() 65 | private final VaadinThemeCreator themeCreator = new VaadinThemeCreator() 66 | 67 | CreateProjectTask() { 68 | description = 'Creates a Vaadin Flow project' 69 | group = 'Vaadin' 70 | } 71 | 72 | @TaskAction 73 | void run() { 74 | 75 | if (applicationBaseTheme && 76 | applicationBaseTheme.toLowerCase() != 'material' && 77 | applicationBaseTheme.toLowerCase() != LUMO) { 78 | throw new GradleException("Wrong base theme value. Valid values are 'lumo' or 'material'") 79 | } 80 | 81 | VaadinFlowPluginExtension vaadin = project.extensions.getByType(VaadinFlowPluginExtension) 82 | AssembleClientDependenciesTask assembleTask = project.tasks.findByName(AssembleClientDependenciesTask.NAME) 83 | VaadinProject vaadinProject = new VaadinProject( 84 | applicationName: applicationName ?: project.name.capitalize(), 85 | applicationPackage : applicationPackage ?: "com.example.${project.name.toLowerCase()}", 86 | applicationBaseTheme :applicationBaseTheme ?: LUMO, 87 | rootDirectory : project.projectDir, 88 | webappDirectory: assembleTask.webappDir, 89 | productionMode : vaadin.productionMode, 90 | compatibilityMode: vaadin.compatibilityMode, 91 | projectType: ProjectType.get(project), 92 | applicationType: ApplicationType.get(project) 93 | ) 94 | 95 | projectCreator.generate(vaadinProject) 96 | 97 | themeCreator.generateCssTheme(vaadinProject) 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/CreateWebTemplateTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.tasks 19 | 20 | import com.devsoap.vaadinflow.creators.ComponentCreator 21 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 22 | import com.devsoap.vaadinflow.models.ProjectType 23 | import com.devsoap.vaadinflow.models.WebTemplate 24 | 25 | import org.gradle.api.DefaultTask 26 | import org.gradle.api.tasks.Input 27 | import org.gradle.api.tasks.Optional 28 | import org.gradle.api.tasks.TaskAction 29 | import org.gradle.api.tasks.options.Option 30 | 31 | /** 32 | * Creates a new Web Template 33 | * 34 | * @author John Ahlroos 35 | * @since 1.0 36 | */ 37 | class CreateWebTemplateTask extends DefaultTask { 38 | 39 | static final String NAME = 'vaadinCreateWebTemplate' 40 | 41 | @Input 42 | @Optional 43 | @Option(option = 'name', description = 'Template name') 44 | String templateName 45 | 46 | @Input 47 | @Optional 48 | @Option(option = 'package', description = 'Template package') 49 | String templatePackage 50 | 51 | @Input 52 | @Optional 53 | @Option(option = 'tag', description = 'Template tag') 54 | String templateTag 55 | 56 | private final ComponentCreator componentCreator = new ComponentCreator() 57 | 58 | CreateWebTemplateTask() { 59 | group = 'Vaadin' 60 | description = 'Creates a new Web Template' 61 | } 62 | 63 | @TaskAction 64 | void run() { 65 | templateName = templateName ?: 'ExampleWebTemplate' 66 | templatePackage = templatePackage ?: 'com.example.' + project.name.toLowerCase() 67 | templateTag = templateTag ?: templateName.replaceAll(/\B[A-Z]/) { '-' + it }.toLowerCase() 68 | 69 | AssembleClientDependenciesTask assembleTask = project.tasks.findByName(AssembleClientDependenciesTask.NAME) 70 | VaadinFlowPluginExtension vaadin = project.extensions.findByType(VaadinFlowPluginExtension) 71 | componentCreator.generate new WebTemplate( 72 | componentName : templateName, 73 | componentPackage : templatePackage, 74 | componentTag : templateTag, 75 | rootDirectory : project.projectDir, 76 | webappDirectory: assembleTask.webappDir, 77 | projectType: ProjectType.get(project), 78 | compatibilityMode: vaadin.compatibilityMode 79 | ) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/InstallBowerDependenciesTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.tasks 19 | 20 | import com.devsoap.vaadinflow.extensions.VaadinClientDependenciesExtension 21 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 22 | import com.devsoap.vaadinflow.models.ClientPackage 23 | import com.devsoap.vaadinflow.util.ClientPackageUtils 24 | import com.devsoap.vaadinflow.util.VaadinYarnRunner 25 | import com.devsoap.vaadinflow.util.WebJarHelper 26 | import groovy.util.logging.Log 27 | import org.gradle.api.DefaultTask 28 | import org.gradle.api.tasks.CacheableTask 29 | import org.gradle.api.tasks.InputFile 30 | import org.gradle.api.tasks.OutputDirectory 31 | import org.gradle.api.tasks.OutputFile 32 | import org.gradle.api.tasks.PathSensitive 33 | import org.gradle.api.tasks.PathSensitivity 34 | import org.gradle.api.tasks.TaskAction 35 | 36 | /** 37 | * Installs Bower dependencies into the webapp frontend 38 | * 39 | * @author John Ahlroos 40 | * @since 1.0 41 | */ 42 | @Log('LOGGER') 43 | @CacheableTask 44 | class InstallBowerDependenciesTask extends DefaultTask { 45 | 46 | static final String NAME = 'vaadinInstallBowerDependencies' 47 | 48 | protected final File workingDir = project.file(VaadinClientDependenciesExtension.FRONTEND_BUILD_DIR) 49 | 50 | protected final VaadinYarnRunner yarnRunner = new VaadinYarnRunner(project, workingDir) 51 | 52 | @InputFile 53 | @PathSensitive(PathSensitivity.ABSOLUTE) 54 | final File packageJson = new File(workingDir, 'package.json') 55 | 56 | @OutputFile 57 | final File bowerJson = new File(workingDir, 'bower.json') 58 | 59 | @OutputDirectory 60 | final File bowerComponents = new File(workingDir, 'bower_components') 61 | 62 | @OutputDirectory 63 | final File staticResourcesDir = new File(workingDir, 'static') 64 | 65 | InstallBowerDependenciesTask() { 66 | dependsOn( InstallYarnDependenciesTask.NAME ) 67 | onlyIf { 68 | VaadinFlowPluginExtension vaadin = project.extensions.getByType(VaadinFlowPluginExtension) 69 | VaadinClientDependenciesExtension client = project.extensions.getByType(VaadinClientDependenciesExtension) 70 | vaadin.compatibilityMode && (!client.bowerDependencies.isEmpty() || client.compileFromSources) 71 | } 72 | 73 | description = 'Installs Vaadin bower client dependencies' 74 | group = 'vaadin-compatibility' 75 | 76 | inputs.property('bowerDependencies') { 77 | project.extensions.getByType(VaadinClientDependenciesExtension).bowerDependencies 78 | } 79 | 80 | inputs.property('compileFromSources') { 81 | project.extensions.getByType(VaadinClientDependenciesExtension).compileFromSources 82 | } 83 | } 84 | 85 | /** 86 | * Default action. Runs the task. 87 | */ 88 | @TaskAction 89 | void run() { 90 | 91 | LOGGER.info('Creating bower.json...') 92 | VaadinClientDependenciesExtension deps = project.extensions.getByType(VaadinClientDependenciesExtension) 93 | ClientPackage bowerModel = new ClientPackage(name: project.name.toLowerCase(), version: project.version) 94 | .with { model -> 95 | model.dependencies = model.dependencies ?: [:] 96 | deps.bowerDependencies.each { String name, String version -> 97 | model.dependencies[name] = version 98 | } 99 | model 100 | } 101 | bowerJson.text = ClientPackageUtils.toJson(bowerModel) 102 | 103 | LOGGER.info('Installing bower dependencies ... ') 104 | yarnRunner.bowerInstall() 105 | 106 | LOGGER.info('Extracting bower webjars...') 107 | WebJarHelper.unpackWebjars(workingDir, staticResourcesDir, project, bowerComponents.name, true) 108 | 109 | LOGGER.info('Validating bower modules...') 110 | List imports = ClientPackageUtils.findHTMLImportsFromComponents( 111 | null, bowerComponents, workingDir) 112 | deps.bowerDependencies.keySet().each { dep -> 113 | if ( imports.findAll { it.contains( dep.split('/').last()) }.isEmpty()) { 114 | logger.error('HTML entrypoint file for {} not found, is it a Polymer 2 component?', dep) 115 | } 116 | } 117 | 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/VersionCheckTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.tasks 19 | 20 | import com.devsoap.vaadinflow.VaadinFlowPlugin 21 | import com.devsoap.vaadinflow.util.Versions 22 | import groovy.transform.Memoized 23 | import groovy.transform.PackageScope 24 | import groovy.util.logging.Log 25 | import org.gradle.api.DefaultTask 26 | import org.gradle.api.Project 27 | import org.gradle.api.tasks.InputFile 28 | import org.gradle.api.tasks.Optional 29 | import org.gradle.api.tasks.OutputFile 30 | import org.gradle.api.tasks.TaskAction 31 | import org.gradle.util.VersionNumber 32 | 33 | import java.util.concurrent.TimeUnit 34 | import java.util.regex.Matcher 35 | 36 | /** 37 | * Checks the plugin version for a new version 38 | * 39 | * @author John Ahlroos 40 | * @since 1.0 41 | */ 42 | @Log('LOGGER') 43 | class VersionCheckTask extends DefaultTask { 44 | 45 | static final String NAME = 'vaadinPluginVersionCheck' 46 | 47 | static final String VERSION_CACHE_FILE = '.vaadin-gradle-flow-version.check' 48 | 49 | private static final String URL = "https://plugins.gradle.org/plugin/$VaadinFlowPlugin.PLUGIN_ID" 50 | 51 | private final File versionCacheFile = new File(project.buildDir, VERSION_CACHE_FILE) 52 | 53 | VersionCheckTask() { 54 | description = 'Checks if there is a newer version of the plugin available' 55 | group = 'Vaadin' 56 | project.afterEvaluate { 57 | boolean firstRun = false 58 | if (!getVersionCacheFile()) { 59 | new File(project.buildDir, VERSION_CACHE_FILE).with { 60 | it.parentFile.mkdirs() 61 | it.createNewFile() 62 | } 63 | firstRun = true 64 | } 65 | 66 | long cacheAge = System.currentTimeMillis() - getVersionCacheFile().lastModified() 67 | long cacheTime = TimeUnit.DAYS.toMillis(1) 68 | outputs.upToDateWhen { !firstRun && cacheAge < cacheTime } 69 | onlyIf { firstRun || cacheAge > cacheTime } 70 | } 71 | } 72 | 73 | /** 74 | * Checks for a new version 75 | */ 76 | @TaskAction 77 | void run() { 78 | VersionNumber pluginVersion = Versions.version('vaadin.plugin.version') 79 | VersionNumber latestVersion = getLatestReleaseVersion(project) 80 | if (latestVersion > pluginVersion) { 81 | LOGGER.warning "A newer version of the Gradle Vaadin Flow plugin is available ($latestVersion)" 82 | } else { 83 | LOGGER.info('You are using the latest plugin. Excellent!') 84 | } 85 | getVersionCacheFile().text = latestVersion.toString() 86 | } 87 | 88 | /** 89 | * Gets the latest released Gradle plugin version 90 | * 91 | * @return 92 | * the latest released version number 93 | */ 94 | static VersionNumber getLatestReleaseVersion(Project project) { 95 | VersionNumber version = VersionNumber.UNKNOWN 96 | 97 | if (project.gradle.startParameter.offline) { 98 | return version 99 | } 100 | 101 | try { 102 | String html = URL.toURL().text 103 | Matcher matcher = html =~ /Version (\S+)/ 104 | if (matcher.find()) { 105 | version = VersionNumber.parse(matcher.group(1)) 106 | } 107 | } catch (IOException | URISyntaxException e) { 108 | version = VersionNumber.UNKNOWN 109 | } 110 | version 111 | } 112 | 113 | /** 114 | * Get version cache file 115 | */ 116 | @OutputFile 117 | protected File getVersionCacheFile() { 118 | versionCacheFile 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/tasks/package-info.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * Contains all the tasks of the plugin. 21 | */ 22 | package com.devsoap.vaadinflow.tasks 23 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/util/ClientPackageUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.util 19 | 20 | import groovy.json.JsonException 21 | import groovy.json.JsonGenerator 22 | import groovy.json.JsonOutput 23 | import groovy.json.JsonSlurper 24 | import groovy.util.logging.Log 25 | 26 | import java.util.logging.Level 27 | 28 | /** 29 | * Utilities for handling bower and npm modules 30 | * 31 | * @author John Ahlroos 32 | * @since 1.1 33 | */ 34 | @Log('LOGGER') 35 | class ClientPackageUtils { 36 | 37 | private static final String BOWER_JSON = 'bower.json' 38 | private static final String PACKAGE_JSON = 'package.json' 39 | private static final String HTML_FILE_TYPE = '.html' 40 | private static final String CSS_FILE_TYPE = '.css' 41 | private static final String NOT_INCLUDED_WARNING = 'module will not be included in production mode bundle.' 42 | 43 | /** 44 | * Searches for HTML imports in module directories 45 | * 46 | * @param nodeModules 47 | * the node module directories 48 | * @param bowerComponents 49 | * the bower module directories 50 | * @param workingDir 51 | * the working directory 52 | * @return 53 | * a list of imports 54 | */ 55 | static List findHTMLImportsFromComponents(File nodeModules, File bowerComponents, File workingDir) { 56 | List imports = [] 57 | 58 | List scanDirs = [] 59 | if (nodeModules && nodeModules.exists()) { 60 | scanDirs.add(nodeModules) 61 | } 62 | if (bowerComponents && bowerComponents.exists()) { 63 | scanDirs.add(bowerComponents) 64 | } 65 | 66 | scanDirs.each { 67 | 68 | LOGGER.info("Searching for html imports in $it") 69 | it.eachDir { dir -> 70 | File bowerJsonFile = new File(dir, '.bower.json') 71 | if (!bowerJsonFile.exists()) { 72 | bowerJsonFile = new File(dir, ClientPackageUtils.BOWER_JSON) 73 | } 74 | if (!bowerJsonFile.exists()) { 75 | bowerJsonFile = new File(dir, ClientPackageUtils.PACKAGE_JSON) 76 | } 77 | if (bowerJsonFile.exists()) { 78 | try { 79 | Object bowerJson = new JsonSlurper().parse(bowerJsonFile) 80 | 81 | List entrypoints = [] 82 | if (bowerJson.main instanceof List) { 83 | entrypoints.addAll(bowerJson.main as List) 84 | } else { 85 | entrypoints.add(bowerJson.main as String) 86 | } 87 | 88 | entrypoints = entrypoints.findAll { 89 | it?.endsWith(ClientPackageUtils.HTML_FILE_TYPE) || 90 | it?.endsWith(ClientPackageUtils.CSS_FILE_TYPE) 91 | } 92 | 93 | if (entrypoints.isEmpty()) { 94 | LOGGER.fine("No entry-point found for ${bowerJson.name}, $NOT_INCLUDED_WARNING") 95 | } 96 | 97 | entrypoints.each { 98 | File resourceFile = new File(dir, it) 99 | String path = (resourceFile.path - workingDir.path).substring(1) 100 | imports.add(path) 101 | } 102 | } catch (JsonException je) { 103 | LOGGER.warning("Failed to parse $bowerJsonFile") 104 | LOGGER.warning(je.message) 105 | } 106 | } else { 107 | LOGGER.info("No bower.json or package.json found in $dir, $NOT_INCLUDED_WARNING") 108 | } 109 | } 110 | } 111 | imports 112 | } 113 | 114 | /** 115 | * Converts an object into a pretty-printed JSON string 116 | * 117 | * @since 1.3 118 | * @param obj 119 | * the object to convert 120 | * @return 121 | * json string 122 | */ 123 | static String toJson(Object obj) { 124 | JsonOutput.prettyPrint( new JsonGenerator.Options().excludeNulls().build().toJson(obj)) 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/util/HttpUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.util 19 | 20 | /** 21 | * Http request utilities 22 | * 23 | * @author John Ahlroos 24 | * @since 1.0 25 | */ 26 | class HttpUtils { 27 | 28 | private static final String MINUS_ONE_STRING = '-1' 29 | private static final String LOCALHOST = 'localhost' 30 | 31 | /** 32 | * Get the HTTP Proxy url 33 | */ 34 | static String getHttpProxy() { 35 | int proxyPort = Integer.parseInt(System.getProperty('http.proxyPort', MINUS_ONE_STRING)) 36 | if (proxyPort > 0) { 37 | String proxyScheme = System.getProperty('http.proxyScheme', 'http') 38 | String proxyHost = System.getProperty('http.proxyHost', LOCALHOST) 39 | String proxyUser = System.getProperty('http.proxyUser', null) 40 | if (proxyUser) { 41 | String proxyPass = System.getProperty('http.proxyPassword', null) 42 | return "$proxyScheme://$proxyUser:$proxyPass@$proxyHost:$proxyPort" 43 | } 44 | return "$proxyScheme://$proxyHost:$proxyPort" 45 | } 46 | } 47 | 48 | /** 49 | * Get the HTTPS Proxy url 50 | */ 51 | static String getHttpsProxy() { 52 | int proxyPort = Integer.parseInt(System.getProperty('https.proxyPort', MINUS_ONE_STRING)) 53 | if (proxyPort > 0) { 54 | String proxyScheme = System.getProperty('https.proxyScheme', 'https') 55 | String proxyHost = System.getProperty('https.proxyHost', LOCALHOST) 56 | String proxyUser = System.getProperty('https.proxyUser', null) 57 | if (proxyUser) { 58 | String proxyPass = System.getProperty('https.proxyPassword', null) 59 | return "$proxyScheme://$proxyUser:$proxyPass@$proxyHost:$proxyPort" 60 | } 61 | return "$proxyScheme://$proxyHost:$proxyPort" 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/util/LogUtils.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.util 19 | 20 | import groovy.time.TimeCategory 21 | import groovy.time.TimeDuration 22 | import groovy.util.logging.Log 23 | import org.gradle.api.Project 24 | import org.gradle.internal.io.LineBufferingOutputStream 25 | import org.gradle.internal.io.TextStream 26 | 27 | import javax.annotation.Nullable 28 | import java.util.logging.Level 29 | 30 | /** 31 | * Utilities for logging 32 | * 33 | * @author John Ahlroos 34 | * @since 1.0 35 | */ 36 | @Log('LOGGER') 37 | class LogUtils { 38 | 39 | static final OutputStream getLogOutputStream(Level level) { 40 | new LineBufferingOutputStream(new LogStream(level)) 41 | } 42 | 43 | static final T measureTime(String description, Closure closure) { 44 | Date start = new Date() 45 | T result = closure.call() 46 | Date end = new Date() 47 | TimeDuration duration = TimeCategory.minus(end, start) 48 | LOGGER.info("$description. It took $duration") 49 | result 50 | } 51 | 52 | static final void printIfNotPrintedBefore(Project project, String message) { 53 | SingletonPrinter.instance.printIfNotPrintedBefore(project, message) 54 | } 55 | 56 | @Log('LOGGER') 57 | private static class LogStream implements TextStream { 58 | 59 | private final Level level 60 | 61 | LogStream(Level level) { 62 | this.level = level 63 | } 64 | 65 | @Override 66 | void text(String text) { 67 | String trimmedText = text.replaceAll(/\s*$/, '') 68 | if (!trimmedText.blank) { 69 | LOGGER.log(level, trimmedText) 70 | } 71 | } 72 | 73 | @Override 74 | void endOfStream(@Nullable Throwable failure) { 75 | if (failure) { 76 | LOGGER.log(Level.SEVERE, '', failure) 77 | } 78 | } 79 | } 80 | 81 | @Singleton(lazy = false, strict = true) 82 | private static class SingletonPrinter { 83 | 84 | private final Map messageStatus = [:] 85 | 86 | void printIfNotPrintedBefore(Project project, String message) { 87 | messageStatus.putIfAbsent(message, true) 88 | if ( messageStatus[message] ) { 89 | if (project.logger.lifecycleEnabled) { 90 | project.logger.lifecycle(message) 91 | } 92 | messageStatus[message] = false 93 | } 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/util/PackagingUtil.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.util 19 | 20 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 21 | import com.devsoap.vaadinflow.tasks.AssembleClientDependenciesTask 22 | import org.gradle.api.Project 23 | import org.gradle.api.file.CopySpec 24 | import org.gradle.api.file.DuplicatesStrategy 25 | import org.gradle.jvm.tasks.Jar 26 | 27 | import java.nio.file.Paths 28 | 29 | /** 30 | * Configures the Spring Boot plugin to support the Vaadin resources 31 | * 32 | * @author John Ahlroos 33 | * @since 1.1 34 | */ 35 | class PackagingUtil { 36 | 37 | private static final String WEBAPP_GEN = 'webapp-gen' 38 | 39 | /** 40 | * Includes static resources in the Jar output 41 | * 42 | * @param task 43 | * the Jar task to add the resources to 44 | */ 45 | static void includeResourcesInJar(Jar jar, String resourcesPath) { 46 | 47 | Project project = jar.project 48 | 49 | // Include web-app dirs 50 | AssembleClientDependenciesTask assembleTask = project.tasks.findByName(AssembleClientDependenciesTask.NAME) 51 | File webappDir = assembleTask.webappDir 52 | jar.from(webappDir) { CopySpec spec -> 53 | spec.duplicatesStrategy = DuplicatesStrategy.EXCLUDE 54 | spec.into(resourcesPath) 55 | } 56 | 57 | // Include web-app gen 58 | File webappGen = Paths.get(project.buildDir.canonicalPath, WEBAPP_GEN).toFile() 59 | jar.from(webappGen) { CopySpec spec -> 60 | spec.duplicatesStrategy = DuplicatesStrategy.EXCLUDE 61 | spec.into(resourcesPath) 62 | } 63 | 64 | // Copy static frontend files into compilation result 65 | VaadinFlowPluginExtension vaadin = jar.project.extensions.getByType(VaadinFlowPluginExtension) 66 | if (vaadin.productionMode) { 67 | File frontend = new File(webappDir, 'frontend') 68 | if (frontend.exists()) { 69 | jar.from(frontend) { CopySpec spec -> 70 | spec.duplicatesStrategy = DuplicatesStrategy.EXCLUDE 71 | spec.into(resourcesPath + '/frontend-es5') 72 | } 73 | jar.from(frontend) { CopySpec spec -> 74 | spec.duplicatesStrategy = DuplicatesStrategy.EXCLUDE 75 | spec.into(resourcesPath + '/frontend-es6') 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/util/TemplateWriter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.util 19 | 20 | import groovy.text.SimpleTemplateEngine 21 | import groovy.text.TemplateEngine 22 | import groovy.transform.Memoized 23 | import groovy.transform.builder.Builder 24 | import groovy.util.logging.Log 25 | 26 | /** 27 | * Builder for creating writers for writing a template to the file system 28 | * 29 | * @author John Ahlroos 30 | * @since 1.0 31 | */ 32 | @Builder 33 | @Log('LOGGER') 34 | class TemplateWriter { 35 | 36 | String templateFileName 37 | 38 | File targetDir 39 | 40 | String targetFileName 41 | 42 | Map substitutions 43 | 44 | /** 45 | * Writes the template to the file-system 46 | * 47 | * @return 48 | * the file of the generated template 49 | */ 50 | File write() { 51 | Objects.nonNull(templateFileName) 52 | Objects.nonNull(targetDir) 53 | 54 | targetFileName = targetFileName ?: templateFileName 55 | substitutions = substitutions ?: [:] 56 | 57 | writeTemplateFromString(generateTemplate()) 58 | } 59 | 60 | /** 61 | * Get template as String 62 | * 63 | * @return 64 | * the template result as a string 65 | */ 66 | String toString() { 67 | Objects.nonNull(templateFileName) 68 | Objects.nonNull(targetDir) 69 | 70 | targetFileName = targetFileName ?: templateFileName 71 | substitutions = substitutions ?: [:] 72 | 73 | generateTemplate() 74 | } 75 | 76 | private String generateTemplate() { 77 | URL templateUrl = TemplateWriter.classLoader.getResource("templates/${templateFileName}.template") 78 | if ( !templateUrl ) { 79 | throw new FileNotFoundException("Could not find template 'templates/${templateFileName}.template'") 80 | } 81 | 82 | TemplateEngine engine = new SimpleTemplateEngine() 83 | engine.createTemplate(templateUrl).make(substitutions.withDefault { null }) 84 | } 85 | 86 | private File writeTemplateFromString(String templateContent) { 87 | File targetFile = new File(targetDir, targetFileName) 88 | if ( !targetFile.exists() ) { 89 | targetFile.parentFile.mkdirs() 90 | targetFile.createNewFile() 91 | } 92 | 93 | if ( !targetFile.canWrite() ) { 94 | throw new FileNotFoundException("Could not write to target file $targetFile.canonicalPath") 95 | } 96 | 97 | LOGGER.info "Writing template $templateFileName to ${targetFile.canonicalPath}" 98 | targetFile.write(templateContent) 99 | targetFile 100 | } 101 | 102 | /** 103 | * Ensures that the string can be used as a Java Class Name 104 | */ 105 | static String makeStringJavaCompatible(String string) { 106 | if (!string) { 107 | return null 108 | } 109 | List collector = [] 110 | List collector2 = [] 111 | string.chars.collect(collector) { ch -> 112 | if (collector.empty) { 113 | Character.isJavaIdentifierStart(ch) ? ch : '' 114 | } else { 115 | Character.isJavaIdentifierPart(ch) ? ch : ' ' 116 | } 117 | }.join('').tokenize().collect(collector2) { t -> 118 | collector2.empty ? t : t.capitalize() 119 | }.join('') 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/util/Versions.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.util 19 | 20 | import groovy.util.logging.Log 21 | import org.gradle.util.VersionNumber 22 | 23 | /** 24 | * Class for resolving application and library versions 25 | * 26 | * @author John Ahlroos 27 | * @since 1.0 28 | */ 29 | @Log('LOGGER') 30 | class Versions { 31 | 32 | private Versions() { } 33 | 34 | /** 35 | * Get a version for a key 36 | * 37 | * @param key 38 | * the key to get the version for 39 | * @return 40 | * the version number. If not found VersionNumber.UNKNOWN is returned. 41 | */ 42 | static final VersionNumber version(String key) { 43 | String versionString = rawVersion(key) 44 | versionString != null ? VersionNumber.parse(versionString) : VersionNumber.UNKNOWN 45 | } 46 | 47 | /** 48 | * Get a raw version string for a key 49 | * 50 | * @param key 51 | * the key to get the version for 52 | * @return 53 | * the raw version number as it has been defined in the properties file 54 | */ 55 | static final String rawVersion(String key) { 56 | Properties properties = new Properties() 57 | Versions.getResourceAsStream( '/versions.properties' ).with { 58 | properties.load(it) 59 | } 60 | if (properties.get(key)) { 61 | return properties.get(key).toString() 62 | } 63 | LOGGER.warning("Failed to find key $key in versions.properties") 64 | null 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/groovy/com/devsoap/vaadinflow/util/package-info.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * Utility methods and classes 21 | */ 22 | package com.devsoap.vaadinflow.util 23 | -------------------------------------------------------------------------------- /src/main/resources/templates/.npmrc.template: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | <% parameters.each { k,v -> 3 | if(v instanceof String) { 4 | println "$k=\"$v\"" 5 | } else { 6 | println "$k=$v" 7 | } 8 | } %> -------------------------------------------------------------------------------- /src/main/resources/templates/.yarnrc.template: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | <% parameters.each { k,v -> 4 | if(v instanceof String) { 5 | println "$k \"$v\"" 6 | } else { 7 | println "$k $v" 8 | } 9 | } %> -------------------------------------------------------------------------------- /src/main/resources/templates/AppTheme.css.template: -------------------------------------------------------------------------------- 1 | /* 2 | * This file contains the Application theme 3 | */ 4 | label { 5 | color: var(--lumo-primary-text-color); 6 | } 7 | label.clicked { 8 | color: var(--lumo-success-color); 9 | } -------------------------------------------------------------------------------- /src/main/resources/templates/AppView.groovy.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.button.Button 4 | import com.vaadin.flow.component.html.Label 5 | import com.vaadin.flow.component.orderedlayout.VerticalLayout 6 | import com.vaadin.flow.component.page.BodySize 7 | import com.vaadin.flow.component.page.Viewport 8 | import com.vaadin.flow.router.Route 9 | 10 | /** 11 | * The main view of the application 12 | */ 13 | @Route('') 14 | @BodySize(height = '100vh', width = '100vw') 15 | @Viewport('width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes') 16 | class ${applicationName}View extends VerticalLayout { 17 | 18 | ${applicationName}View() { 19 | 20 | className = 'app-view' 21 | 22 | add new Label('Hello Groovy app!') 23 | 24 | add new Button('Click me!', { event -> 25 | event.source.with { 26 | text = 'Clicked!' 27 | className = 'clicked' 28 | } 29 | }) 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/resources/templates/AppView.java.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage}; 2 | 3 | import com.vaadin.flow.component.button.Button; 4 | import com.vaadin.flow.component.html.Label; 5 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 6 | import com.vaadin.flow.component.page.BodySize; 7 | import com.vaadin.flow.component.page.Viewport; 8 | import com.vaadin.flow.component.dependency.StyleSheet; 9 | import com.vaadin.flow.router.Route; 10 | 11 | /** 12 | * The main view of the application 13 | */ 14 | @Route("") 15 | @BodySize(height = "100vh", width = "100vw") 16 | @Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes") 17 | public class ${applicationName}View extends VerticalLayout { 18 | 19 | public ${applicationName}View() { 20 | setClassName("app-view"); 21 | 22 | Label hello = new Label("Hello Gradle app!"); 23 | add(hello); 24 | 25 | Button button = new Button("Click me", event -> { 26 | hello.setText("Clicked!"); 27 | hello.setClassName("clicked"); 28 | }); 29 | add(button); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/resources/templates/AppView.kt.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.button.Button 4 | import com.vaadin.flow.component.html.Label 5 | import com.vaadin.flow.component.orderedlayout.VerticalLayout 6 | import com.vaadin.flow.component.page.BodySize 7 | import com.vaadin.flow.component.page.Viewport 8 | import com.vaadin.flow.router.Route 9 | 10 | /** 11 | * The main view of the application 12 | */ 13 | @Route("") 14 | @BodySize(height = "100vh", width = "100vw") 15 | @Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes") 16 | class ${applicationName}View : VerticalLayout() { 17 | init { 18 | className = "app-view" 19 | 20 | val hello = Label("Hello Kotlin app!") 21 | add(hello) 22 | 23 | val button = Button("Click me") { 24 | hello.text = "Clicked!" 25 | hello.className = "clicked" 26 | } 27 | add(button) 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/resources/templates/AppView.v14.groovy.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.button.Button 4 | import com.vaadin.flow.component.dependency.CssImport 5 | import com.vaadin.flow.component.html.Label 6 | import com.vaadin.flow.component.orderedlayout.VerticalLayout 7 | import com.vaadin.flow.component.page.BodySize 8 | import com.vaadin.flow.component.page.Viewport 9 | import com.vaadin.flow.router.Route 10 | import com.vaadin.flow.theme.${applicationBaseTheme.toLowerCase()}.${applicationBaseTheme.toLowerCase().capitalize()} 11 | import com.vaadin.flow.theme.Theme 12 | 13 | /** 14 | * The main view of the application 15 | */ 16 | @Route('') 17 | @Theme(${applicationBaseTheme.toLowerCase().capitalize()}.class) 18 | @BodySize(height = '100vh', width = '100vw') 19 | @Viewport('width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes') 20 | @CssImport("./theme.css") 21 | class ${applicationName}View extends VerticalLayout { 22 | 23 | ${applicationName}View() { 24 | 25 | className = 'app-view' 26 | 27 | add new Label('Hello Groovy app!') 28 | 29 | def button = new Button('This is a Vaadin Button, Click me!') { event -> 30 | hello.setClassName('clicked'); 31 | hello.setText('Clicked! Next is a custom Polymer template button, Click it!'); 32 | event.getSource().setVisible(false); 33 | add(new HelloButton()); 34 | } 35 | add button 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/resources/templates/AppView.v14.java.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage}; 2 | 3 | import com.vaadin.flow.component.button.Button; 4 | import com.vaadin.flow.component.dependency.CssImport; 5 | import com.vaadin.flow.component.html.Label; 6 | import com.vaadin.flow.component.orderedlayout.VerticalLayout; 7 | import com.vaadin.flow.component.page.BodySize; 8 | import com.vaadin.flow.component.page.Viewport; 9 | import com.vaadin.flow.router.Route; 10 | import com.vaadin.flow.theme.${applicationBaseTheme.toLowerCase()}.${applicationBaseTheme.toLowerCase().capitalize()}; 11 | import com.vaadin.flow.theme.Theme; 12 | 13 | /** 14 | * The main view of the application 15 | */ 16 | @Route("") 17 | @Theme(${applicationBaseTheme.toLowerCase().capitalize()}.class) 18 | @BodySize(height = "100vh", width = "100vw") 19 | @Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes") 20 | @CssImport("./theme.css") 21 | public class ${applicationName}View extends VerticalLayout { 22 | 23 | public ${applicationName}View() { 24 | setClassName("app-view"); 25 | 26 | Label hello = new Label("Hello Gradle app!"); 27 | add(hello); 28 | 29 | Button button = new Button("This is a Vaadin Button, Click me!", event -> { 30 | hello.setClassName("clicked"); 31 | hello.setText("Clicked! Next is a custom Polymer template button, Click it!"); 32 | event.getSource().setVisible(false); 33 | add(new HelloButton()); 34 | }); 35 | 36 | add(button); 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/resources/templates/AppView.v14.kt.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.button.Button 4 | import com.vaadin.flow.component.dependency.CssImport 5 | import com.vaadin.flow.component.html.Label 6 | import com.vaadin.flow.component.orderedlayout.VerticalLayout 7 | import com.vaadin.flow.component.page.BodySize 8 | import com.vaadin.flow.component.page.Viewport 9 | import com.vaadin.flow.router.Route 10 | import com.vaadin.flow.theme.${applicationBaseTheme.toLowerCase()}.${applicationBaseTheme.toLowerCase().capitalize()} 11 | import com.vaadin.flow.theme.Theme 12 | 13 | /** 14 | * The main view of the application 15 | */ 16 | @Route("") 17 | @Theme(${applicationBaseTheme.toLowerCase().capitalize()}::class) 18 | @BodySize(height = "100vh", width = "100vw") 19 | @Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes") 20 | @CssImport("./theme.css") 21 | class ${applicationName}View : VerticalLayout() { 22 | init { 23 | className = "app-view" 24 | 25 | val hello = Label("Hello Kotlin app!") 26 | add(hello) 27 | 28 | val button = Button("Click me") { event -> 29 | hello.text = "Clicked!" 30 | hello.className = "clicked" 31 | event.source.isVisible = false 32 | add(HelloButton()) 33 | } 34 | add(button) 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/resources/templates/Component.groovy.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Component 4 | import com.vaadin.flow.component.Tag 5 | import com.vaadin.flow.component.Synchronize 6 | 7 | @Tag('${componentTag}') 8 | class ${componentName} extends Component { 9 | 10 | ${componentName}(String value) { 11 | this.value = value 12 | } 13 | 14 | @Synchronize('change') 15 | String getValue() { 16 | element.getProperty("value"); 17 | } 18 | 19 | void setValue(String value) { 20 | element.setProperty('value', value); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/templates/Component.java.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage}; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.Tag; 5 | import com.vaadin.flow.component.Synchronize; 6 | 7 | @Tag("${componentTag}") 8 | public class ${componentName} extends Component { 9 | 10 | public ${componentName}(String value) { 11 | setValue(value); 12 | } 13 | 14 | @Synchronize("change") 15 | public String getValue() { 16 | return getElement().getProperty("value"); 17 | } 18 | 19 | public void setValue(String value) { 20 | getElement().setProperty("value", value); 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/main/resources/templates/Component.kt.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage}; 2 | 3 | import com.vaadin.flow.component.Component 4 | import com.vaadin.flow.component.Synchronize 5 | import com.vaadin.flow.component.Tag 6 | 7 | @Tag("${componentTag}") 8 | class ${componentName}(value: String) : Component() { 9 | 10 | init { 11 | setValue(value) 12 | } 13 | 14 | @Synchronize("change") 15 | fun getValue() : String { 16 | return element.getProperty("value") 17 | } 18 | 19 | fun setValue(value:String) { 20 | element.setProperty("value", value) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/templates/Composite.groovy.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.html.Label 4 | import com.vaadin.flow.component.html.Input 5 | import com.vaadin.flow.component.Composite 6 | import ${componentBaseClass} 7 | 8 | class ${componentName} extends Composite<${componentBaseClass.split('\\.').last()}> { 9 | 10 | private final Label label = new Label() 11 | 12 | private final Input input = new Input() 13 | 14 | ${componentName}(String labelText, String value) { 15 | label.text = labelText 16 | input.value = value 17 | content.add label, input 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/resources/templates/Composite.java.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage}; 2 | 3 | import com.vaadin.flow.component.html.Label; 4 | import com.vaadin.flow.component.html.Input; 5 | import com.vaadin.flow.component.Composite; 6 | import ${componentBaseClass}; 7 | 8 | public class ${componentName} extends Composite<${componentBaseClass.split('\\.').last()}> { 9 | 10 | private final Label label = new Label(); 11 | 12 | private final Input input = new Input(); 13 | 14 | public ${componentName}(String labelText, String value) { 15 | label.setText(labelText); 16 | input.setValue(value); 17 | getContent().add(label, input); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/resources/templates/Composite.kt.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Composite 4 | import ${componentBaseClass} 5 | import com.vaadin.flow.component.html.Input 6 | import com.vaadin.flow.component.html.Label 7 | 8 | class ${componentName}(labelText : String, value : String) : Composite<${componentBaseClass.split('\\.').last()}>() { 9 | 10 | private val label : Label = Label() 11 | 12 | private val input : Input = Input() 13 | 14 | init { 15 | label.text = labelText 16 | input.value = value 17 | content.add(label, input) 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/resources/templates/HelloButton.groovy.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.HasComponents 4 | import com.vaadin.flow.component.Tag 5 | import com.vaadin.flow.component.dependency.JsModule 6 | import com.vaadin.flow.component.polymertemplate.EventHandler 7 | import com.vaadin.flow.component.polymertemplate.Id 8 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate 9 | import com.vaadin.flow.dom.Element 10 | import com.vaadin.flow.templatemodel.TemplateModel 11 | 12 | @Tag("hello-button") 13 | @JsModule("./hello-button.js") 14 | class HelloButton extends PolymerTemplate { 15 | 16 | @Id("caption") 17 | private Element caption 18 | 19 | HelloButton() { 20 | caption.text = 'Click Me!' 21 | } 22 | 23 | @EventHandler 24 | private void sayHello() { 25 | caption.text = 'You clicked, how can I help you? Click again!' 26 | parent.ifPresent { HasComponents layout -> layout.add(new HelloButton()) } 27 | } 28 | 29 | interface HelloButtonModel extends TemplateModel { } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/resources/templates/HelloButton.java.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage}; 2 | 3 | import com.vaadin.flow.component.HasComponents; 4 | import com.vaadin.flow.component.Tag; 5 | import com.vaadin.flow.component.dependency.JsModule; 6 | import com.vaadin.flow.component.polymertemplate.EventHandler; 7 | import com.vaadin.flow.component.polymertemplate.Id; 8 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate; 9 | import com.vaadin.flow.dom.Element; 10 | import com.vaadin.flow.templatemodel.TemplateModel; 11 | 12 | @Tag("hello-button") 13 | @JsModule("./hello-button.js") 14 | public class HelloButton extends PolymerTemplate { 15 | 16 | @Id("caption") 17 | private Element caption; 18 | 19 | public HelloButton() { 20 | caption.setText("Click Me!"); 21 | } 22 | 23 | @EventHandler 24 | private void sayHello() { 25 | caption.setText("You clicked, how can I help you? Click again!"); 26 | getParent().ifPresent(layout -> ((HasComponents)layout).add(new HelloButton())); 27 | } 28 | 29 | public interface HelloButtonModel extends TemplateModel { } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/resources/templates/HelloButton.kt.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.HasComponents 4 | import com.vaadin.flow.component.Tag 5 | import com.vaadin.flow.component.dependency.JsModule 6 | import com.vaadin.flow.component.polymertemplate.EventHandler 7 | import com.vaadin.flow.component.polymertemplate.Id 8 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate 9 | import com.vaadin.flow.dom.Element 10 | import com.vaadin.flow.templatemodel.TemplateModel 11 | 12 | @Tag("hello-button") 13 | @JsModule("./hello-button.js") 14 | class HelloButton : PolymerTemplate() { 15 | 16 | @Id("caption") 17 | private Element caption 18 | 19 | init { 20 | caption.setText("Click Me!") 21 | } 22 | 23 | @EventHandler 24 | private fun sayHello() { 25 | caption.setText("You clicked, how can I help you? Click again!") 26 | parent.ifPresent { layout -> (layout as HasComponents).add(HelloButton())} 27 | } 28 | 29 | interface HelloButtonModel : TemplateModel { } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/resources/templates/Servlet.groovy.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.server.VaadinServlet 4 | import com.vaadin.flow.server.VaadinServletConfiguration 5 | 6 | import javax.servlet.annotation.WebServlet 7 | 8 | 9 | @WebServlet(urlPatterns = '/*', name = '${applicationName}Servlet', asyncSupported = true) 10 | @VaadinServletConfiguration(ui = ${applicationName}UI, productionMode = ${productionMode}) 11 | class ${applicationName}Servlet extends VaadinServlet { } -------------------------------------------------------------------------------- /src/main/resources/templates/Servlet.java.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage}; 2 | 3 | import com.vaadin.flow.server.VaadinServlet; 4 | import com.vaadin.flow.server.VaadinServletConfiguration; 5 | 6 | import javax.servlet.annotation.WebServlet; 7 | 8 | 9 | @WebServlet(urlPatterns = "/*", name = "${applicationName}Servlet", asyncSupported = true) 10 | @VaadinServletConfiguration(ui = ${applicationName}UI.class, productionMode = ${productionMode}) 11 | public class ${applicationName}Servlet extends VaadinServlet { } -------------------------------------------------------------------------------- /src/main/resources/templates/Servlet.kt.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.server.VaadinServlet 4 | import com.vaadin.flow.server.VaadinServletConfiguration 5 | 6 | import javax.servlet.annotation.WebServlet 7 | 8 | 9 | @WebServlet(urlPatterns = ["/*"], name = "${applicationName}Servlet", asyncSupported = true) 10 | @VaadinServletConfiguration(ui = ${applicationName}UI::class, productionMode = ${productionMode}) 11 | class ${applicationName}Servlet : VaadinServlet() -------------------------------------------------------------------------------- /src/main/resources/templates/SpringBootApplication.groovy.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | class ${applicationName}Application { 8 | 9 | /** 10 | * The main method makes it possible to run the application as a plain Java 11 | * application which starts embedded web server via Spring Boot. 12 | * 13 | * @param args 14 | * command line parameters 15 | */ 16 | static void main(String[] args) { 17 | SpringApplication.run(${applicationName}Application, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/templates/SpringBootApplication.java.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage}; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ${applicationName}Application { 8 | 9 | /** 10 | * The main method makes it possible to run the application as a plain Java 11 | * application which starts embedded web server via Spring Boot. 12 | * 13 | * @param args 14 | * command line parameters 15 | */ 16 | public static void main(String[] args) { 17 | SpringApplication.run(${applicationName}Application.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/templates/SpringBootApplication.kt.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import org.springframework.boot.SpringApplication 4 | import org.springframework.boot.autoconfigure.SpringBootApplication 5 | 6 | @SpringBootApplication 7 | open class ${applicationName}Application { } 8 | 9 | /** 10 | * The main method makes it possible to run the application as a plain Java 11 | * application which starts embedded web server via Spring Boot. 12 | * 13 | * @param args 14 | * command line parameters 15 | */ 16 | fun main(args: Array) { 17 | SpringApplication.run(${applicationName}Application::class.java, *args) 18 | } -------------------------------------------------------------------------------- /src/main/resources/templates/UI.groovy.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.dependency.HtmlImport 4 | import com.vaadin.flow.component.UI 5 | import com.vaadin.flow.theme.${applicationBaseTheme.toLowerCase()}.${applicationBaseTheme.toLowerCase().capitalize()} 6 | import com.vaadin.flow.theme.Theme 7 | 8 | @HtmlImport("frontend://styles/${applicationTheme}") 9 | @Theme(${applicationBaseTheme.toLowerCase().capitalize()}) 10 | class ${applicationName}UI extends UI { } 11 | -------------------------------------------------------------------------------- /src/main/resources/templates/UI.java.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage}; 2 | 3 | import com.vaadin.flow.component.dependency.HtmlImport; 4 | import com.vaadin.flow.component.UI; 5 | import com.vaadin.flow.theme.${applicationBaseTheme.toLowerCase()}.${applicationBaseTheme.toLowerCase().capitalize()}; 6 | import com.vaadin.flow.theme.Theme; 7 | 8 | @HtmlImport("frontend://styles/${applicationTheme}") 9 | @Theme(${applicationBaseTheme.toLowerCase().capitalize()}.class) 10 | public class ${applicationName}UI extends UI { } 11 | -------------------------------------------------------------------------------- /src/main/resources/templates/UI.kt.template: -------------------------------------------------------------------------------- 1 | package ${applicationPackage} 2 | 3 | import com.vaadin.flow.component.dependency.HtmlImport 4 | import com.vaadin.flow.component.UI 5 | import com.vaadin.flow.theme.${applicationBaseTheme.toLowerCase()}.${applicationBaseTheme.toLowerCase().capitalize()} 6 | import com.vaadin.flow.theme.Theme 7 | 8 | @HtmlImport("frontend://styles/${applicationTheme}") 9 | @Theme(${applicationBaseTheme.toLowerCase().capitalize()}::class) 10 | class ${applicationName}UI : UI() 11 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebComponent.groovy.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Component 4 | import com.vaadin.flow.component.Tag 5 | import com.vaadin.flow.component.dependency.HtmlImport 6 | 7 | @Tag('${componentTag}') 8 | @HtmlImport('frontend://${packageManager}/${dependencyPackage}/${dependencyHtml}.html') 9 | class ${componentName} extends Component { 10 | 11 | ${componentName}() { 12 | 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebComponent.java.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage}; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.Tag; 5 | import com.vaadin.flow.component.dependency.HtmlImport; 6 | 7 | @Tag("${componentTag}") 8 | @HtmlImport("frontend://${packageManager}/${dependencyPackage}/${dependencyHtml}.html") 9 | public class ${componentName} extends Component { 10 | 11 | public ${componentName}() { 12 | 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebComponent.kt.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.Tag; 5 | import com.vaadin.flow.component.dependency.HtmlImport; 6 | 7 | @Tag("${componentTag}") 8 | @HtmlImport("frontend://${packageManager}/${dependencyPackage}/${dependencyHtml}.html") 9 | class ${componentName} : Component() { 10 | 11 | init { 12 | 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebComponent.v14.groovy.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Component 4 | import com.vaadin.flow.component.Tag 5 | import com.vaadin.flow.component.dependency.JsModule 6 | import com.vaadin.flow.component.dependency.NpmPackage 7 | 8 | @Tag('${componentTag}') 9 | @NpmPackage(value = '${dependencyArtifact}', version = '${dependencyVersion}') 10 | @JsModule('${dependencyArtifact}/${dependencyHtml}.js') 11 | class ${componentName} extends Component { 12 | 13 | ${componentName}() { 14 | 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebComponent.v14.java.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage}; 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.Tag; 5 | import com.vaadin.flow.component.dependency.JsModule; 6 | import com.vaadin.flow.component.dependency.NpmPackage; 7 | 8 | @Tag("${componentTag}") 9 | @NpmPackage(value = "${dependencyArtifact}", version = "${dependencyVersion}") 10 | @JsModule("${dependencyArtifact}/${dependencyHtml}.js") 11 | public class ${componentName} extends Component { 12 | 13 | public ${componentName}() { 14 | 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebComponent.v14.kt.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Component; 4 | import com.vaadin.flow.component.Tag; 5 | import com.vaadin.flow.component.dependency.JsModule; 6 | import com.vaadin.flow.component.dependency.NpmPackage; 7 | 8 | @Tag("${componentTag}") 9 | @NpmPackage(value = "${dependencyArtifact}", version = "${dependencyVersion}") 10 | @JsModule("${dependencyArtifact}/${dependencyHtml}.js") 11 | class ${componentName} : Component() { 12 | 13 | init { 14 | 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.groovy.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Tag 4 | import com.vaadin.flow.component.dependency.HtmlImport 5 | import com.vaadin.flow.component.polymertemplate.EventHandler 6 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate 7 | import com.vaadin.flow.templatemodel.TemplateModel 8 | 9 | @Tag('${componentTag}') 10 | @HtmlImport('templates/${componentName}.html') 11 | class ${componentName} extends PolymerTemplate<${componentName}Model> { 12 | 13 | ${componentName}() { 14 | model.caption = 'Hello template!' 15 | } 16 | 17 | @EventHandler 18 | private void sayHello() { 19 | model.caption = 'You clicked, how can I help you?' 20 | } 21 | 22 | static interface ${componentName}Model extends TemplateModel { 23 | void setCaption(String greeting); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.html.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.java.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage}; 2 | 3 | import com.vaadin.flow.component.Tag; 4 | import com.vaadin.flow.component.dependency.HtmlImport; 5 | import com.vaadin.flow.component.polymertemplate.EventHandler; 6 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate; 7 | import com.vaadin.flow.templatemodel.TemplateModel; 8 | 9 | @Tag("${componentTag}") 10 | @HtmlImport("templates/${componentName}.html") 11 | public class ${componentName} extends PolymerTemplate<${componentName}.${componentName}Model> { 12 | 13 | ${componentName}() { 14 | getModel().setCaption("Hello template!"); 15 | } 16 | 17 | @EventHandler 18 | private void sayHello() { 19 | getModel().setCaption("You clicked, how can I help you?"); 20 | } 21 | 22 | public interface ${componentName}Model extends TemplateModel { 23 | void setCaption(String greeting); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.js.template: -------------------------------------------------------------------------------- 1 | import {PolymerElement} from '@polymer/polymer/polymer-element.js'; 2 | 3 | class ${componentName}Element extends PolymerElement { 4 | 5 | static get template() { 6 | return '
[[caption]]
'; 7 | } 8 | 9 | static get is() { 10 | return '${componentTag}'; 11 | } 12 | } 13 | customElements.define(${componentName}Element.is, ${componentName}Element); 14 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.kt.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Tag 4 | import com.vaadin.flow.component.dependency.HtmlImport 5 | import com.vaadin.flow.component.polymertemplate.EventHandler 6 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate 7 | import com.vaadin.flow.templatemodel.TemplateModel 8 | 9 | @Tag("${componentTag}") 10 | @HtmlImport("templates/${componentName}.html") 11 | class ${componentName} : PolymerTemplate<${componentName}.${componentName}Model>() { 12 | 13 | init { 14 | model.setCaption("Hello template") 15 | } 16 | 17 | @EventHandler 18 | private fun sayHello() { 19 | model.setCaption("You clicked, how can I help you?"); 20 | } 21 | 22 | interface ${componentName}Model : TemplateModel { 23 | fun setCaption(greeting: String) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.tpl.template: -------------------------------------------------------------------------------- 1 | link (rel:'import', href: '../bower_components/polymer/polymer-element.html') 2 | 3 | 'dom-module' ( id:'${componentTag}') { 4 | template { 5 | div (id:'caption', 'on-click' : 'sayHello') { 6 | yield '[[caption]]' 7 | } 8 | } 9 | 10 | script(''' 11 | class ${componentName} extends Polymer.Element { 12 | static get is() { 13 | return '${componentTag}' 14 | } 15 | } 16 | customElements.define(${componentName}.is, ${componentName}); 17 | ''') 18 | } -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.v14.groovy.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Tag 4 | import com.vaadin.flow.component.dependency.JsModule 5 | import com.vaadin.flow.component.polymertemplate.EventHandler 6 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate 7 | import com.vaadin.flow.templatemodel.TemplateModel 8 | 9 | @Tag('${componentTag}') 10 | @JsModule('./${componentName}Element.js') 11 | class ${componentName} extends PolymerTemplate<${componentName}Model> { 12 | 13 | ${componentName}() { 14 | model.caption = 'Hello template!' 15 | } 16 | 17 | @EventHandler 18 | private void sayHello() { 19 | model.caption = 'You clicked, how can I help you?' 20 | } 21 | 22 | static interface ${componentName}Model extends TemplateModel { 23 | void setCaption(String greeting); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.v14.java.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage}; 2 | 3 | import com.vaadin.flow.component.Tag; 4 | import com.vaadin.flow.component.dependency.JsModule; 5 | import com.vaadin.flow.component.polymertemplate.EventHandler; 6 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate; 7 | import com.vaadin.flow.templatemodel.TemplateModel; 8 | 9 | @Tag("${componentTag}") 10 | @JsModule("./${componentName}Element.js") 11 | public class ${componentName} extends PolymerTemplate<${componentName}.${componentName}Model> { 12 | 13 | ${componentName}() { 14 | getModel().setCaption("Hello template!"); 15 | } 16 | 17 | @EventHandler 18 | private void sayHello() { 19 | getModel().setCaption("You clicked, how can I help you?"); 20 | } 21 | 22 | public interface ${componentName}Model extends TemplateModel { 23 | void setCaption(String greeting); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/templates/WebTemplate.v14.kt.template: -------------------------------------------------------------------------------- 1 | package ${componentPackage} 2 | 3 | import com.vaadin.flow.component.Tag 4 | import com.vaadin.flow.component.dependency.JsModule 5 | import com.vaadin.flow.component.polymertemplate.EventHandler 6 | import com.vaadin.flow.component.polymertemplate.PolymerTemplate 7 | import com.vaadin.flow.templatemodel.TemplateModel 8 | 9 | @Tag("${componentTag}") 10 | @HtmlImport("./${componentName}Element.js") 11 | class ${componentName} : PolymerTemplate<${componentName}.${componentName}Model>() { 12 | 13 | init { 14 | model.setCaption("Hello template") 15 | } 16 | 17 | @EventHandler 18 | private fun sayHello() { 19 | model.setCaption("You clicked, how can I help you?"); 20 | } 21 | 22 | interface ${componentName}Model : TemplateModel { 23 | fun setCaption(greeting: String) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/templates/hello-button.js.template: -------------------------------------------------------------------------------- 1 | import {PolymerElement} from '@polymer/polymer/polymer-element.js'; 2 | import {html} from '@polymer/polymer/lib/utils/html-tag.js'; 3 | 4 | class HelloButtonElement extends PolymerElement { 5 | 6 | static get template() { 7 | return html` 8 | 12 | [[caption]] 13 | `; 14 | } 15 | 16 | static get is() { 17 | return 'hello-button'; 18 | } 19 | } 20 | customElements.define(HelloButtonElement.is, HelloButtonElement); 21 | -------------------------------------------------------------------------------- /src/main/resources/templates/theme.js.template: -------------------------------------------------------------------------------- 1 | const div = document.createElement('div'); 2 | div.innerHTML = ''; 3 | document.head.insertBefore(div.firstElementChild, document.head.firstChild); -------------------------------------------------------------------------------- /src/main/resources/templates/webpack.config.js.template: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { BabelMultiTargetPlugin } = require('webpack-babel-multi-target-plugin'); 3 | 4 | module.exports = { 5 | mode: 'production', 6 | entry: './src/index.js', 7 | 8 | resolve: { 9 | alias: { 10 | 'Frontend' : '.' 11 | }, 12 | modules: [ 13 | ${ moduleDirs.collect { "path.resolve(__dirname, '$it')" }.join(',\n') } 14 | ] 15 | }, 16 | 17 | output: { 18 | filename: `vaadin-[name]-[contenthash].cache.js`, 19 | path: path.resolve(__dirname, '${targetPath}') 20 | }, 21 | 22 | module: { 23 | rules: [ 24 | { 25 | test: /\\.js\$/, 26 | use: [BabelMultiTargetPlugin.loader()] 27 | }, 28 | { 29 | test: /\\.css\$/i, 30 | use: ['raw-loader'] 31 | } 32 | ] 33 | }, 34 | 35 | plugins: [ 36 | new BabelMultiTargetPlugin({ 37 | babel: { 38 | presetOptions: { 39 | useBuiltIns: false 40 | } 41 | }, 42 | targets: { 43 | 'es6': { 44 | browsers: [ 45 | 'last 1 Chrome major versions' 46 | ], 47 | }, 48 | 'es5': { 49 | browsers: [ 50 | 'ie 11' 51 | ], 52 | tagAssetsWithKey: true, 53 | } 54 | } 55 | }) 56 | ] 57 | }; 58 | 59 | -------------------------------------------------------------------------------- /src/main/resources/templates/yarn-flat.js.template: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | * Copyright 2018-2019 Devsoap Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | const os = require("os"); 18 | const pty = require("${ptyPackage}"); 19 | const semver = require("semver"); 20 | const shell = os.platform() === 'win32' ? 'powershell.exe' : 'yarn'; 21 | let params = ["install", '${productionMode}', "--flat"]; 22 | if (os.platform() === 'win32') { 23 | params.unshift('yarn'); 24 | } 25 | function semverComparator(a, b) { 26 | if (semver.lt(a, b)) { 27 | return -1; 28 | } else if (semver.gt(a, b)) { 29 | return 1; 30 | } else { 31 | return 0; 32 | } 33 | } 34 | const proc = pty.spawn(shell, params, { 35 | name: "xterm", 36 | cols: 1000, 37 | rows: 30, 38 | env: process.env, 39 | cwd: "${distDir}" 40 | }); 41 | let buff = ""; 42 | proc.on("data", function(data) { 43 | buff += data.toString(); 44 | if (buff.match(/Answer\\?:/g)) { 45 | const suitableVersion = buff.match(/suitable version for "(\\S+)"/); 46 | if(suitableVersion == null) return; 47 | const packageName = suitableVersion[1]; 48 | const lines = buff.split(/\\r?\\n/g) 49 | const cleanLines = lines.map(line => line.replace( 50 | /[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '').trim()) 51 | const alternatives = cleanLines.filter(line => line.match(/^[0-9]\\).*/)) 52 | const resolvedLines = alternatives.filter(line => line.match("which resolved to")) 53 | const versions = resolvedLines.map(line => line.match(/"(\\S+)"\$/)[1]); 54 | const sorted = versions.slice(0).sort(semverComparator); 55 | const highestVersion = sorted[sorted.length - 1]; 56 | const choice = versions.indexOf(highestVersion) + 1; 57 | console.log("Choosing " + packageName + "@" + highestVersion + " (" + choice + ")"); 58 | proc.write(choice.toString() + "\\r\\n"); 59 | buff = ""; 60 | } 61 | }); 62 | proc.on("error", err => { 63 | console.error(err) 64 | }); 65 | -------------------------------------------------------------------------------- /src/main/resources/vaadin-plugin.gdsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | def vaadinType = 'com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension' 19 | def vaadinClientType = 'com.devsoap.vaadinflow.extensions.VaadinClientDependenciesExtension' 20 | def devsoapType = 'com.devsoap.license.DevsoapLicenseExtension' 21 | def vaadinProperty = 'vaadin' 22 | def vaadinClientProperty = 'vaadinClientDependencies' 23 | def devsoapProperty = 'devsoap' 24 | def vaadinCtx = context(ctype: vaadinType) 25 | def gradleType = 'gradle' 26 | def gradleArtifactRepositoryType = 'org.gradle.api.artifacts.repositories.ArtifactRepository' 27 | def gradleDependencyType = 'org.gradle.api.artifacts.Dependency' 28 | def scriptContext = context(scriptType: gradleType, filetypes:[gradleType], scope: scriptScope()) 29 | def closureCtx = context(scriptType: gradleType, filetypes:[gradleType], scope: closureScope()) 30 | 31 | contributor(vaadinCtx, { 32 | if(enclosingCall('repositories')) { 33 | method name: 'snapshots', type: gradleArtifactRepositoryType 34 | method name: 'prereleases', type: gradleArtifactRepositoryType 35 | method name: 'addons', type: gradleArtifactRepositoryType 36 | method name: 'repositories', type: "java.util.Collection<${gradleArtifactRepositoryType}>" 37 | 38 | } else if(enclosingCall('dependencies')) { 39 | method name: 'platform', type: gradleDependencyType 40 | method name: 'core', type: gradleDependencyType 41 | method name: 'springBoot', type: gradleDependencyType 42 | method name: 'bom', type: gradleDependencyType 43 | method name: 'servletApi', type: gradleDependencyType 44 | method name: 'slf4j', type: gradleDependencyType 45 | method name: 'groovy', type: gradleDependencyType 46 | method name: 'lumoTheme', type: gradleDependencyType 47 | method name: 'materialTheme', type: gradleDependencyType 48 | 49 | } else if(!enclosingMember()){ 50 | method name: 'autoconfigure', type: Void.name, params: [:] 51 | property name: "version", type: String.name 52 | property name: "unsupportedVersion", type: Boolean.name 53 | property name: 'productionMode', type: Boolean.name 54 | property name: 'compatibilityMode', type: Boolean.name 55 | property name: 'baseTheme', type: String.name 56 | property name: 'whitelistedPackages', type: String[].name 57 | property name: 'scanStrategy', type: String.name 58 | } 59 | }) 60 | 61 | contributor(closureCtx, { 62 | if(enclosingCall('repositories') || enclosingCall('dependencies')) { 63 | property name: vaadinProperty, type: vaadinType 64 | } 65 | if(enclosingCall(vaadinProperty)) { 66 | property name: "version", type: String.name 67 | property name: "unsupportedVersion", type: Boolean.name 68 | property name: 'productionMode', type: Boolean.name 69 | property name: 'compatibilityMode', type: Boolean.name 70 | property name: 'baseTheme', type: String.name 71 | property name: 'whitelistedPackages', type: String[].name 72 | property name: 'scanStrategy', type: String.name 73 | } 74 | if(enclosingCall(vaadinClientProperty)) { 75 | property name: 'offlineCachePath', type: String.name 76 | property name: 'compileFromSources', type: Boolean.name 77 | method name: 'yarn', params: ['version' : String.name, 'dependency' : String.name] 78 | method name: 'yarn', params: ['dependencyNotation' : String.name] 79 | method name: 'npm', params: ['version' : String.name, 'dependency' : String.name] 80 | method name: 'npm', params: ['dependencyNotation' : String.name] 81 | } 82 | if(enclosingCall(devsoapProperty)) { 83 | property name: 'email', type: String.name 84 | property name: 'key', type: String.name 85 | } 86 | }) 87 | 88 | contributor(scriptContext, { 89 | property name: vaadinProperty, type: vaadinType 90 | property name: vaadinClientProperty, type: vaadinClientType 91 | property name: devsoapProperty, type: devsoapType 92 | method name: vaadinProperty, params: ['config': Closure.name], type: Void.name 93 | method name: vaadinClientProperty, params: ['config': Closure.name], type: Void.name 94 | }) 95 | -------------------------------------------------------------------------------- /src/main/resources/versions.properties: -------------------------------------------------------------------------------- 1 | vaadin.plugin.version=@version@ 2 | vaadin.plugin.signature=@signature@ 3 | vaadin.plugin.gradle.version=6.0 4 | vaadin.default.version=15.+ 5 | vaadin.supported.versions=10,11,12,13,14,15 6 | servlet.version=4.0.1 7 | slf4j.simple.version=1.7.25 8 | node.plugin.version=1.3.1 9 | polymer.cli.version=1.9.1 10 | polymer.bundler.version=4.0.4 11 | npm.version=6.7.0 12 | node.version=11.15.0 13 | windows.node.version=10.16.3 14 | yarn.version=1.12.3 15 | windows.yarn.version=1.9.4 16 | bower.version=1.8.4 17 | vaadin.statistics.version=1.0.0-optout 18 | vaadin.production.mode.version=1.2.2 19 | groovy.version=2.4.+ 20 | gretty.jetty.version=9.4.15.v20190215 21 | webpack.version=v4.39.0 22 | webpack.cli.version=3.3.6 23 | webcomponentsjs.version=2.2.10 24 | node.pty.version=0.8.1 25 | node.pty.prebuilt.version=0.7.6 26 | babel.runtime.version=7.5.5 27 | bable.multitarget.plugin.version=2.2.0 28 | devsoap.license.version=1.0.16 -------------------------------------------------------------------------------- /src/test/groovy/com/devsoap/vaadinflow/util/VaadinYarnRunnerTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2020 Devsoap Inc. 3 | * 4 | * Licensed under the Creative Commons Attribution-NoDerivatives 4.0 5 | * International Public License (the "License"); you may not use this file 6 | * except in compliance with the License. 7 | * 8 | * You may obtain a copy of the License at 9 | * 10 | * https://creativecommons.org/licenses/by-nd/4.0/ 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package com.devsoap.vaadinflow.util 19 | 20 | import com.devsoap.vaadinflow.VaadinFlowPlugin 21 | import com.devsoap.vaadinflow.extensions.VaadinClientDependenciesExtension 22 | import com.devsoap.vaadinflow.extensions.VaadinFlowPluginExtension 23 | import com.moowork.gradle.node.NodeExtension 24 | import com.moowork.gradle.node.variant.Variant 25 | import org.gradle.api.Project 26 | import org.gradle.process.ExecResult 27 | import org.gradle.testfixtures.ProjectBuilder 28 | import spock.lang.Specification 29 | 30 | import java.nio.file.Paths 31 | 32 | /** 33 | * Test for VaadinYarnRunner 34 | * 35 | * @author John Ahlroos 36 | * @since 1.0 37 | */ 38 | class VaadinYarnRunnerTest extends Specification { 39 | 40 | private VaadinYarnRunner runner 41 | private File packageJson 42 | private File workingDir 43 | private Project project 44 | 45 | protected void setup() { 46 | File testProjectDir = File.createTempDir('junit', '') 47 | workingDir = Paths.get(testProjectDir.canonicalPath, 'build', 'frontend').toFile() 48 | workingDir.mkdirs() 49 | 50 | packageJson = new File(workingDir, 'package.json') 51 | packageJson.text = '{}' 52 | 53 | project = new ProjectBuilder().withProjectDir(testProjectDir).build() 54 | 55 | project.plugins.apply(VaadinFlowPlugin) 56 | 57 | project.extensions.getByType(NodeExtension).with { 58 | variant = new Variant() 59 | variant.windows = false 60 | } 61 | 62 | project.extensions.getByType(VaadinFlowPluginExtension).with { 63 | compatibilityMode = true 64 | } 65 | 66 | runner = new TestRunner(project, workingDir, Mock(ExecResult)) 67 | } 68 | 69 | void 'offline cache path is set in yarn.rc'() { 70 | setup: 71 | project.extensions.getByType(VaadinClientDependenciesExtension).offlineCachePath = '/foo/bar' 72 | when: 73 | runner.init() 74 | File yarnRc = new File(workingDir, '.yarnrc') 75 | then: 76 | yarnRc.exists() 77 | yarnRc.text.contains('yarn-offline-mirror "/foo/bar"') 78 | } 79 | 80 | void 'package.json contains scripts'() { 81 | when: 82 | runner.init() 83 | then: 84 | packageJson.exists() 85 | packageJson.text.contains('"polymer": "./node_modules/polymer-cli/bin/polymer.js"') 86 | packageJson.text.contains('"polymer-bundler": "./node_modules/polymer-bundler/lib/bin/polymer-bundler.js"') 87 | packageJson.text.contains('"bower": "./node_modules/bower/bin/bower"') 88 | } 89 | 90 | void 'package.json contains scripts with node reference on Windows'() { 91 | setup: 92 | project.extensions.getByType(NodeExtension).variant.with { 93 | windows = true 94 | nodeExec = 'C:/path/to/windows/node.exe' 95 | } 96 | when: 97 | runner.init() 98 | then: 99 | packageJson.exists() 100 | packageJson.text.contains( 101 | '"polymer": "C:/path/to/windows/node.exe ./node_modules/polymer-cli/bin/polymer.js"') 102 | packageJson.text.contains( 103 | '"polymer-bundler": "C:/path/to/windows/node.exe ./node_modules/polymer-bundler/lib/bin/polymer-bundler.js"') 104 | packageJson.text.contains( 105 | '"bower": "C:/path/to/windows/node.exe ./node_modules/bower/bin/bower"') 106 | } 107 | 108 | private static class TestRunner extends VaadinYarnRunner { 109 | 110 | private final ExecResult result 111 | 112 | TestRunner(Project project, File workingDir, ExecResult result) { 113 | super(project, workingDir) 114 | this.result = result 115 | } 116 | 117 | @Override 118 | protected ExecResult doExecute() { 119 | result 120 | } 121 | } 122 | } 123 | --------------------------------------------------------------------------------