Skip to content

Commit b948615

Browse files
mcollovatimshabarov
andcommitted
fix!: prevent lumo utility classes to be imported automatically (#23074)
Fixes #22467 --------- Co-authored-by: Mikhail Shabarov <[email protected]>
1 parent 8b58171 commit b948615

File tree

7 files changed

+100
-25
lines changed

7 files changed

+100
-25
lines changed

flow-server/src/main/java/com/vaadin/flow/server/frontend/TaskUpdateThemeImport.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@
1919
import java.io.IOException;
2020
import java.nio.file.Paths;
2121
import java.util.Arrays;
22+
import java.util.HashMap;
23+
import java.util.HashSet;
2224
import java.util.List;
25+
import java.util.Map;
26+
import java.util.Set;
2327
import java.util.stream.Collectors;
2428

2529
import org.slf4j.Logger;
2630
import org.slf4j.LoggerFactory;
31+
import tools.jackson.databind.JsonNode;
2732

2833
import com.vaadin.experimental.FeatureFlags;
2934
import com.vaadin.flow.theme.ThemeDefinition;
@@ -108,6 +113,7 @@ public void execute() throws ExecutionFailedException {
108113
throw new ExecutionFailedException(
109114
"Unable to write theme import file", e);
110115
}
116+
warnAboutLumoImports();
111117
}
112118

113119
private void verifyThemeDirectoryExistence()
@@ -204,6 +210,46 @@ private List<String> getAppThemePossiblePaths(String themePath) {
204210
themePathInStaticResources, themePathInClassPathResources);
205211
}
206212

213+
private void warnAboutLumoImports() {
214+
Map<String, JsonNode> themeJsonContents = new HashMap<>();
215+
ThemeValidationUtil.collectJarPackagedThemes(options,
216+
themeJsonContents);
217+
String themeName = theme.getName();
218+
try {
219+
ThemeUtils.getThemeJson(themeName, options.getFrontendDirectory())
220+
.ifPresent(prjTheme -> ThemeValidationUtil
221+
.collectThemeJsonContentsInFrontend(options,
222+
themeJsonContents, themeName, prjTheme));
223+
} catch (IllegalArgumentException ex) {
224+
// ignore errors if the theme folder does not exist.
225+
// such a case is handled elsewhere
226+
}
227+
228+
// Inspect used theme
229+
Set<String> themesWithLumoImport = new HashSet<>();
230+
String inspectedThemeName = themeName;
231+
while (inspectedThemeName != null
232+
&& themeJsonContents.containsKey(inspectedThemeName)) {
233+
JsonNode themeJson = themeJsonContents.remove(inspectedThemeName);
234+
if (themeJson.has("lumoImports")) {
235+
themesWithLumoImport.add(inspectedThemeName);
236+
}
237+
if (themeJson.has("parent")) {
238+
inspectedThemeName = themeJson.get("parent").stringValue();
239+
} else {
240+
inspectedThemeName = null;
241+
}
242+
}
243+
if (!themesWithLumoImport.isEmpty()) {
244+
getLogger().warn(
245+
"""
246+
The 'lumoImports' property detected in theme(s) '{}' is no longer supported in Vaadin 25. \
247+
All modules except 'utility' are now loaded automatically when extending Lumo theme. \
248+
To load utility classes, add '@StyleSheet(Lumo.UTILITY_STYLESHEET)' annotation to 'AppShellConfigurator' implementor.""",
249+
themesWithLumoImport);
250+
}
251+
}
252+
207253
Logger getLogger() {
208254
return LoggerFactory.getLogger(TaskUpdateThemeImport.class);
209255
}

flow-server/src/main/java/com/vaadin/flow/server/frontend/ThemeValidationUtil.java

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,7 @@ public static boolean themeConfigurationChanged(Options options,
6464
FrontendDependenciesScanner frontendDependencies) {
6565
Map<String, JsonNode> themeJsonContents = new HashMap<>();
6666

67-
if (options.getJarFiles() != null) {
68-
options.getJarFiles().stream().filter(File::exists)
69-
.filter(file -> !file.isDirectory())
70-
.forEach(jarFile -> getPackagedThemeJsonContents(jarFile,
71-
themeJsonContents));
72-
}
67+
collectJarPackagedThemes(options, themeJsonContents);
7368

7469
Optional<String> maybeThemeName = Optional
7570
.ofNullable(frontendDependencies.getThemeDefinition())
@@ -133,6 +128,27 @@ public static boolean themeConfigurationChanged(Options options,
133128
return false;
134129
}
135130

131+
/**
132+
* Collects packaged themes defined in JAR files based on the provided
133+
* options and stores their JSON contents in the given map.
134+
*
135+
* @param options
136+
* the configuration options that include the list of JAR files
137+
* to scan for packaged theme definitions
138+
* @param themeJsonContents
139+
* a map to store the JSON contents of themes found within the
140+
* JAR files, with the theme name as the key
141+
*/
142+
static void collectJarPackagedThemes(Options options,
143+
Map<String, JsonNode> themeJsonContents) {
144+
if (options.getJarFiles() != null) {
145+
options.getJarFiles().stream().filter(File::exists)
146+
.filter(file -> !file.isDirectory())
147+
.forEach(jarFile -> getPackagedThemeJsonContents(jarFile,
148+
themeJsonContents));
149+
}
150+
}
151+
136152
/**
137153
* Checks if theme has legacy Shadow DOM stylesheets in
138154
* {@literal <theme>/components} folder and if their content has changed.
@@ -231,7 +247,22 @@ private static boolean hasNewAssetsOrImports(JsonNode contentsInStats,
231247
&& (moreThanOneKey || noParentEntry);
232248
}
233249

234-
private static void collectThemeJsonContentsInFrontend(Options options,
250+
/**
251+
* Recursively collects and stores the JSON contents of a theme and its
252+
* parent themes (if applicable) from the frontend directory.
253+
*
254+
* @param options
255+
* the configuration options that include frontend settings, such
256+
* as the frontend directory path
257+
* @param themeJsonContents
258+
* a map to store the JSON contents of themes found in the
259+
* frontend directory, using the theme name as the key
260+
* @param themeName
261+
* the name of the theme currently being processed
262+
* @param themeJson
263+
* the JSON representation of the theme currently being processed
264+
*/
265+
static void collectThemeJsonContentsInFrontend(Options options,
235266
Map<String, JsonNode> themeJsonContents, String themeName,
236267
JsonNode themeJson) {
237268
Optional<String> parentThemeInFrontend = ThemeUtils

flow-server/src/main/resources/plugins/application-theme-plugin/theme-generator.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,6 @@ function writeThemeFiles(themeFolder, themeName, themeProperties, options) {
111111
let filename = basename(styles);
112112
let variable = camelCase(filename);
113113

114-
if (themeProperties.lumoImports) {
115-
imports.push(`import lumoUtil from '@vaadin/vaadin-lumo-styles/utility.css?inline';\n`);
116-
shadowOnlyCss.push(`removers.push(injectGlobalCss(lumoUtil.toString(), '', target));\n `);
117-
}
118-
119114
/* Theme */
120115
globalFileContent.push(parentThemeGlobalImport);
121116
if (useDevServerOrInProductionMode) {
@@ -198,16 +193,6 @@ function writeThemeFiles(themeFolder, themeName, themeProperties, options) {
198193

199194
themeFileContent += imports.join('');
200195

201-
if (themeProperties.lumoImports) {
202-
themeFileContent += `if(!document.getElementById("lumoUtil")) {
203-
const styleTag = document.createElement('style');
204-
styleTag.type = 'text/css';
205-
styleTag.id = 'lumoUtil';
206-
styleTag.textContent = lumoUtil.toString();
207-
document.head.prepend(styleTag);
208-
}`;
209-
}
210-
211196
// Don't format as the generated file formatting will get wonky!
212197
// If targets check that we only register the style parts once, checks exist for global css and component css
213198
const themeFileApply = `

flow-server/src/main/resources/plugins/application-theme-plugin/theme-handle.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* for application theme plugin.
2020
*/
2121
import { existsSync, readFileSync } from 'fs';
22-
import { resolve } from 'path';
22+
import { resolve, basename } from 'path';
2323
import { writeThemeFiles } from './theme-generator.js';
2424
import { writeCssFiles } from './css-theme-generator.js';
2525
import { copyStaticAssets, copyThemeResources } from './theme-copy.js';
@@ -153,7 +153,7 @@ function handleThemes(themeName, themesFolder, options, logger) {
153153
if (existsSync(themeFolder)) {
154154
logger.debug('Found theme ', themeName, ' in folder ', themeFolder);
155155

156-
const themeProperties = getThemeProperties(themeFolder, options);
156+
const themeProperties = getThemeProperties(themeFolder, options, logger);
157157

158158
// If theme has parent handle parent theme immediately.
159159
if (themeProperties.parent) {
@@ -176,7 +176,7 @@ function handleThemes(themeName, themesFolder, options, logger) {
176176
return false;
177177
}
178178

179-
function getThemeProperties(themeFolder, options) {
179+
function getThemeProperties(themeFolder, options, logger) {
180180
const themePropertyFile = resolve(themeFolder, 'theme.json');
181181
let outputFolder;
182182
if (options.javaResourceFolder) {
@@ -205,6 +205,15 @@ function getThemeProperties(themeFolder, options) {
205205
}
206206
let themeJson = JSON.parse(themePropertyFileAsString);
207207
themeJson.autoInjectComponents = componentFeature;
208+
209+
if (themeJson.lumoImports) {
210+
const themeName = basename(themeFolder);
211+
logger.warn(
212+
`The 'lumoImports' property detected in theme '${themeName}' is no longer supported in Vaadin 25. ` +
213+
"All modules except 'utility' are now loaded automatically when extending Lumo theme. " +
214+
"To load utility classes, add '@StyleSheet(Lumo.UTILITY_STYLESHEET)' annotation to 'AppShellConfigurator' implementor."
215+
);
216+
}
208217
return themeJson;
209218
}
210219

flow-tests/test-legacy-frontend/frontend/themes/app-theme/styles.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@import '@vaadin/vaadin-lumo-styles/utility.css';
12
html,
23
:host {
34
--lumo-primary-text-color: #008000;

flow-tests/test-theme-no-polymer/src/main/frontend/themes/app-theme/styles.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@import '@vaadin/vaadin-lumo-styles/utility.css';
12
html,
23
:host {
34
--lumo-primary-text-color: #008000;

flow-tests/test-themes/src/main/java/com/vaadin/flow/uitest/ui/theme/AppShell.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.vaadin.flow.uitest.ui.theme;
1717

18+
import com.vaadin.flow.component.dependency.CssImport;
1819
import com.vaadin.flow.component.dependency.NpmPackage;
1920
import com.vaadin.flow.component.dependency.StyleSheet;
2021
import com.vaadin.flow.component.page.AppShellConfigurator;
@@ -28,5 +29,6 @@
2829
"svgs/regular/**:npm/icons" })
2930
@LoadDependenciesOnStartup
3031
@StyleSheet("context://aura/fake-aura.css")
32+
@CssImport("@vaadin/vaadin-lumo-styles/utility.css")
3133
public class AppShell implements AppShellConfigurator {
3234
}

0 commit comments

Comments
 (0)