Skip to content

Commit 2d4ad91

Browse files
authored
feat: Look up for the theme assets in the default dev bundle (#15566)
Looks up for the theme files in the default dev bundle if the theme files are not found in the project's frontend theme directory. Also improves the message thrown if the file is not found anywhere.
1 parent 3bd3b16 commit 2d4ad91

File tree

19 files changed

+324
-30
lines changed

19 files changed

+324
-30
lines changed

flow-plugins/flow-maven-plugin/src/test/java/com/vaadin/flow/plugin/maven/PrepareFrontendMojoTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,15 @@ public void writeTokenFile_devModePropertiesAreWritten()
207207
}
208208

209209
@Test
210-
public void mavenGoal_when_packageJsonMissing() throws Exception {
210+
public void mavenGoal_when_packageJsonMissing_shouldNotGenerateDefault()
211+
throws Exception {
211212
Assert.assertFalse(FileUtils.fileExists(packageJson));
212213
mojo.execute();
213-
assertPackageJsonContent();
214+
Assert.assertFalse(FileUtils.fileExists(packageJson));
214215
}
215216

216217
@Test
217-
public void should_keepDependencies_when_packageJsonExists()
218+
public void should_updateAndkeepDependencies_when_packageJsonExists()
218219
throws Exception {
219220
JsonObject json = TestUtils.getInitialPackageJson();
220221
json.put("dependencies", Json.createObject());

flow-plugins/flow-plugin-base/src/main/java/com/vaadin/flow/plugin/base/BuildFrontendUtil.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static com.vaadin.flow.server.Constants.GENERATED_TOKEN;
2323
import static com.vaadin.flow.server.Constants.JAVA_RESOURCE_FOLDER_TOKEN;
2424
import static com.vaadin.flow.server.Constants.NPM_TOKEN;
25+
import static com.vaadin.flow.server.Constants.PACKAGE_JSON;
2526
import static com.vaadin.flow.server.Constants.PROJECT_FRONTEND_GENERATED_DIR_TOKEN;
2627
import static com.vaadin.flow.server.InitParameters.NODE_DOWNLOAD_ROOT;
2728
import static com.vaadin.flow.server.InitParameters.NODE_VERSION;
@@ -156,8 +157,10 @@ public static void prepareFrontend(PluginAdapterBase adapter)
156157
.withBuildDirectory(adapter.buildFolder())
157158
.withJarFrontendResourcesFolder(
158159
getJarFrontendResourcesFolder(adapter))
159-
.createMissingPackageJson(true).enableImportsUpdate(false)
160-
.enablePackagesUpdate(false).runNpmInstall(false)
160+
.createMissingPackageJson(
161+
new File(adapter.npmFolder(), PACKAGE_JSON).exists())
162+
.enableImportsUpdate(false).enablePackagesUpdate(false)
163+
.runNpmInstall(false)
161164
.withFrontendGeneratedFolder(adapter.generatedTsFolder())
162165
.withNodeVersion(adapter.nodeVersion())
163166
.withNodeDownloadRoot(nodeDownloadRootURI)

flow-server/src/main/java/com/vaadin/flow/server/Constants.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,10 +441,20 @@ public final class Constants implements Serializable {
441441
// Non-default port currently not supported (#7970)
442442
public static final int SPRING_BOOT_DEFAULT_LIVE_RELOAD_PORT = 35729;
443443

444+
/**
445+
* The name of the default dev bundle for the Express Build mode.
446+
*/
447+
public static final String DEV_BUNDLE_NAME = "vaadin-dev-bundle";
448+
444449
/**
445450
* The path part where dev-bundle is located inside the jar.
446451
*/
447-
public static final String DEV_BUNDLE_JAR_PATH = "vaadin-dev-bundle/";
452+
public static final String DEV_BUNDLE_JAR_PATH = DEV_BUNDLE_NAME + "/";
453+
454+
/**
455+
* The directory name inside dev bundle for the frontend assets.
456+
*/
457+
public static final String ASSETS = "assets";
448458

449459
private Constants() {
450460
// prevent instantiation constants class only

flow-server/src/main/java/com/vaadin/flow/server/StaticFileServer.java

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.Collections;
3636
import java.util.HashMap;
3737
import java.util.Map;
38+
import java.util.regex.Matcher;
3839
import java.util.regex.Pattern;
3940

4041
import org.slf4j.Logger;
@@ -76,7 +77,7 @@ public class StaticFileServer implements StaticFileHandler {
7677

7778
// Matcher to match string starting with '/themes/[theme-name]/'
7879
public static final Pattern APP_THEME_PATTERN = Pattern
79-
.compile("^\\/themes\\/[\\s\\S]+?\\/");
80+
.compile("^\\/themes\\/([\\s\\S]+?)\\/");
8081

8182
// Mapped uri is for the jar file
8283
static final Map<URI, Integer> openFileSystems = new HashMap<>();
@@ -263,6 +264,7 @@ public boolean serveStaticResource(HttpServletRequest request,
263264
} else if (APP_THEME_PATTERN.matcher(filenameWithPath).find()) {
264265
if (!deploymentConfiguration.enableDevServer()) {
265266
resourceUrl = findAssetInFrontendThemesOrDevBundle(
267+
vaadinService,
266268
deploymentConfiguration.getProjectFolder(),
267269
filenameWithPath);
268270
} else {
@@ -317,26 +319,52 @@ && isIncorrectWebjarPath(filenameWithPath)) {
317319
return true;
318320
}
319321

320-
private static URL findAssetInFrontendThemesOrDevBundle(File projectFolder,
321-
String assetPath) throws IOException {
322+
private static URL findAssetInFrontendThemesOrDevBundle(
323+
VaadinService vaadinService, File projectFolder, String assetPath)
324+
throws IOException {
322325
// First, look for the theme assets in the {project.root}/frontend/
323326
// themes/my-theme folder
324327
File frontendFolder = new File(projectFolder, FrontendUtils.FRONTEND);
325328
File assetInFrontendThemes = new File(frontendFolder, assetPath);
326329
if (assetInFrontendThemes.exists()) {
327330
return assetInFrontendThemes.toURI().toURL();
328331
}
329-
// Or search in the dev-bundle (if the assets come from node_modules)
330-
String assetInDevBundle = "/assets/" + assetPath;
331-
URL assetInDevBundleUrl = FrontendUtils.findBundleFile(projectFolder,
332-
assetInDevBundle);
332+
333+
// Second, look into default dev bundle
334+
Matcher matcher = APP_THEME_PATTERN.matcher(assetPath);
335+
if (!matcher.find()) {
336+
throw new IllegalStateException(
337+
"Asset path should match the theme pattern");
338+
}
339+
340+
final String themeName = matcher.group(1);
341+
String defaultBundleAssetPath = assetPath.replaceFirst(themeName,
342+
Constants.DEV_BUNDLE_NAME);
343+
URL assetInDevBundleUrl = vaadinService.getClassLoader()
344+
.getResource(Constants.DEV_BUNDLE_JAR_PATH + Constants.ASSETS
345+
+ defaultBundleAssetPath);
346+
347+
// Or search in the application dev-bundle (if the assets come from
348+
// node_modules)
349+
if (assetInDevBundleUrl == null) {
350+
String assetInDevBundle = "/" + Constants.ASSETS + "/" + assetPath;
351+
assetInDevBundleUrl = FrontendUtils.findBundleFile(projectFolder,
352+
assetInDevBundle);
353+
}
354+
333355
if (assetInDevBundleUrl == null) {
356+
String assetName = assetPath.substring(
357+
assetPath.indexOf(themeName) + themeName.length());
334358
throw new IllegalStateException(String.format(
335-
"Asset '%s' is not found neither in frontend/themes/theme-name/ "
336-
+ "nor in dev-bundle/assets/. Verify that either the asset "
337-
+ "is available in frontend/themes/theme-name/ folder or it is added "
338-
+ "in the 'assets' block in 'theme.json'.",
339-
assetPath));
359+
"Asset '%1$s' is not found in project frontend directory"
360+
+ ", default Express Build bundle or in the application "
361+
+ "bundle './dev-bundle/assets/'. \n"
362+
+ "Verify that the asset is available in "
363+
+ "'frontend/themes/%2$s/' directory and is added into the "
364+
+ "'assets' block of the 'theme.json' file. \n"
365+
+ "Else verify that the dependency 'com.vaadin:vaadin-dev-bundle' "
366+
+ "is added to your project.",
367+
assetName, themeName));
340368
}
341369
return assetInDevBundleUrl;
342370
}

flow-tests/test-express-build/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<modules>
2929
<module>test-dev-bundle-no-plugin</module>
3030
<module>test-theme-dev-bundle</module>
31+
<module>test-theme-default-dev-bundle</module>
3132
</modules>
3233
</profile>
3334
</profiles>

flow-tests/test-express-build/test-dev-bundle/frontend/themes/vaadin-dev-bundle/styles.css

Whitespace-only changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"assets": {
3+
"line-awesome": {
4+
"dist/line-awesome/css/**": "line-awesome/dist/line-awesome/css",
5+
"dist/line-awesome/fonts/**": "line-awesome/dist/line-awesome/fonts"
6+
}
7+
}
8+
}

flow-tests/test-express-build/test-dev-bundle/pom.xml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
<version>${project.version}</version>
3535
<optional>true</optional>
3636
</dependency>
37+
<dependency>
38+
<groupId>com.vaadin</groupId>
39+
<artifactId>flow-test-lumo</artifactId>
40+
<version>${project.version}</version>
41+
</dependency>
3742
<dependency>
3843
<groupId>org.slf4j</groupId>
3944
<artifactId>slf4j-simple</artifactId>
@@ -49,9 +54,20 @@
4954
</dependencies>
5055
<build>
5156
<plugins>
57+
<plugin>
58+
<groupId>org.apache.maven.plugins</groupId>
59+
<artifactId>maven-jar-plugin</artifactId>
60+
<version>3.3.0</version>
61+
<configuration>
62+
<excludes>
63+
<exclude>**/*Fake*</exclude>
64+
</excludes>
65+
</configuration>
66+
</plugin>
5267
<plugin>
5368
<groupId>com.vaadin</groupId>
5469
<artifactId>flow-dev-bundle-plugin</artifactId>
70+
<version>${project.version}</version>
5571
<executions>
5672
<execution>
5773
<goals>
@@ -92,6 +108,31 @@
92108
</filesets>
93109
</configuration>
94110
</plugin>
111+
<plugin>
112+
<groupId>org.apache.maven.plugins</groupId>
113+
<artifactId>maven-antrun-plugin</artifactId>
114+
<executions>
115+
<execution>
116+
<id>delete-fake-app-conf</id>
117+
<phase>pre-integration-test</phase>
118+
<goals>
119+
<goal>run</goal>
120+
</goals>
121+
<configuration>
122+
<tasks>
123+
<delete>
124+
<!-- Delete FakeAppConf from target/classes to
125+
avoid conflicts between default dev
126+
bundle theme and custom theme in the test
127+
modules, when running
128+
test-express-build with maven -->
129+
<fileset file="${project.build.directory}/classes/com/vaadin/devbundle/FakeAppConf.class"/>
130+
</delete>
131+
</tasks>
132+
</configuration>
133+
</execution>
134+
</executions>
135+
</plugin>
95136

96137
</plugins>
97138
</build>

flow-tests/test-express-build/test-dev-bundle/src/main/java/com/vaadin/devbundle/Deps.java

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.devbundle;
17+
18+
import com.vaadin.flow.component.dependency.JsModule;
19+
import com.vaadin.flow.component.dependency.NpmPackage;
20+
import com.vaadin.flow.component.page.AppShellConfigurator;
21+
import com.vaadin.flow.theme.Theme;
22+
23+
@Theme("vaadin-dev-bundle")
24+
@JsModule("@polymer/paper-input/paper-input.js")
25+
@JsModule("@polymer/paper-checkbox/paper-checkbox.js")
26+
@NpmPackage(value = "@polymer/paper-input", version = "3.0.2")
27+
@NpmPackage(value = "@polymer/paper-checkbox", version = "3.0.1")
28+
@NpmPackage(value = "line-awesome", version = "1.3.0")
29+
public class FakeAppConf implements AppShellConfigurator {
30+
31+
}

0 commit comments

Comments
 (0)