Skip to content

Commit c880995

Browse files
authored
fix: ensure exported WebComponent adds absolute links to document.css (#21124)
When using a development bundle, WebComponentBootstrapHandler adds a <link> tag to the embedding document that references document.css for all used themes (application and parents). However, the URL is relative to the embedding document instead of being an absolute URL to the CSS resource. Additionally, the <link> tag is added even if the theme does not provide a document.css file, potentially causing 404 errors at runtime. This change ensures that the link URL is calculated based on the request and that it only adds tags for existing CSS files. Fixes #21120 Fixes #19620
1 parent b1750a4 commit c880995

File tree

5 files changed

+51
-3
lines changed

5 files changed

+51
-3
lines changed

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

+31
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,12 @@ protected static Collection<Element> getStylesheetTags(
16281628
* Gives a links for referencing the custom theme stylesheet files
16291629
* (typically styles.css or document.css), which are served in express build
16301630
* mode by static file server directly from frontend/themes folder.
1631+
* <p>
1632+
* </p>
1633+
* This method does not verify that the style sheet exists, so it may end up
1634+
* at runtime with broken links. Use
1635+
* {@link #getStylesheetLinks(VaadinContext, String, File)} if you want only
1636+
* links for existing files to be returned.
16311637
*
16321638
* @param context
16331639
* the vaadin context
@@ -1637,7 +1643,32 @@ protected static Collection<Element> getStylesheetTags(
16371643
*/
16381644
protected static Collection<String> getStylesheetLinks(
16391645
VaadinContext context, String fileName) {
1646+
return getStylesheetLinks(context, fileName, null);
1647+
}
1648+
1649+
/**
1650+
* Gives a links for referencing the custom theme stylesheet files
1651+
* (typically styles.css or document.css), which are served in express build
1652+
* mode by static file server directly from frontend/themes folder.
1653+
* <p>
1654+
* </p>
1655+
* This method return links only for existing style sheet files.
1656+
*
1657+
* @param context
1658+
* the vaadin context
1659+
* @param fileName
1660+
* the stylesheet file name to add a reference to
1661+
* @param frontendDirectory
1662+
* the directory where project's frontend files are located.
1663+
*
1664+
* @return the collection of links to be added to the page
1665+
*/
1666+
protected static Collection<String> getStylesheetLinks(
1667+
VaadinContext context, String fileName, File frontendDirectory) {
16401668
return ThemeUtils.getActiveThemes(context).stream()
1669+
.filter(theme -> frontendDirectory == null
1670+
|| ThemeUtils.getThemeFolder(frontendDirectory, theme)
1671+
.toPath().resolve(fileName).toFile().exists())
16411672
.map(theme -> ThemeUtils.getThemeFilePath(theme, fileName))
16421673
.toList();
16431674
}

flow-server/src/main/java/com/vaadin/flow/server/communication/WebComponentBootstrapHandler.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.vaadin.flow.server.communication;
1717

1818
import java.io.BufferedWriter;
19+
import java.io.File;
1920
import java.io.IOException;
2021
import java.io.OutputStreamWriter;
2122
import java.io.Writer;
@@ -429,11 +430,16 @@ protected void writeBootstrapPage(String contentType,
429430
.forEach(element -> ElementUtil.fromJsoup(element)
430431
.ifPresent(elementsForShadows::add));
431432

433+
File frontendDirectory = FrontendUtils
434+
.getProjectFrontendDir(config);
435+
432436
// Add document.css link to the document
433-
BootstrapHandler.getStylesheetLinks(context, "document.css")
437+
BootstrapHandler
438+
.getStylesheetLinks(context, "document.css",
439+
frontendDirectory)
434440
.forEach(link -> UI.getCurrent().getPage().executeJs(
435441
BootstrapHandler.SCRIPT_TEMPLATE_FOR_STYLESHEET_LINK_TAG,
436-
link));
442+
modifyPath(serviceUrl, link)));
437443
}
438444

439445
WebComponentConfigurationRegistry

flow-tests/test-express-build/test-embedding-express-build/src/main/frontend/themes/embedded-theme/theme.json

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"parent": "parent-theme",
23
"documentCss": ["@fortawesome/fontawesome-free/css/all.css"],
34
"assets": {
45
"@fortawesome/fontawesome-free": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/*
2+
Parent theme added only to ensure that exported web components do not add
3+
style sheet link to the document when the theme does not provide a document.css
4+
file
5+
*/

flow-tests/test-express-build/test-embedding-express-build/src/test/java/com/vaadin/flow/webcomponent/ApplicationThemeComponentIT.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.vaadin.flow.webcomponent;
1717

18+
import java.net.URI;
1819
import java.util.List;
1920

2021
import org.junit.Assert;
@@ -222,8 +223,12 @@ public void documentCssLinkAddedToHead() {
222223
final List<WebElement> links = documentHead
223224
.findElements(By.tagName("link"));
224225
Assert.assertEquals(1, links.size());
225-
Assert.assertTrue(links.get(0).getAttribute("href")
226+
String documentCssURL = links.get(0).getAttribute("href");
227+
Assert.assertTrue(documentCssURL
226228
.contains("VAADIN/themes/embedded-theme/document.css"));
229+
URI documentCssURI = URI.create(documentCssURL);
230+
Assert.assertTrue("document.css URL should be absolute, but was "
231+
+ documentCssURL, documentCssURI.isAbsolute());
227232
}
228233

229234
}

0 commit comments

Comments
 (0)