diff --git a/flow-server/src/main/java/com/vaadin/flow/server/frontend/AbstractUpdateImports.java b/flow-server/src/main/java/com/vaadin/flow/server/frontend/AbstractUpdateImports.java index 135d973d582..48a4760e1a8 100644 --- a/flow-server/src/main/java/com/vaadin/flow/server/frontend/AbstractUpdateImports.java +++ b/flow-server/src/main/java/com/vaadin/flow/server/frontend/AbstractUpdateImports.java @@ -71,14 +71,15 @@ abstract class AbstractUpdateImports implements Runnable { + " document.head[before ? 'insertBefore' : 'appendChild'](tpl.content, document.head.firstChild);\n" + "};"; - private static final String CSS_IMPORT = "import $css_%d from '%s';"; + private static final String CSS_IMPORT = "import $cssFromFile_%d from '%s';%n" // + + "const $css_%1$d = typeof $cssFromFile_%1$d === 'string' ? unsafeCSS($cssFromFile_%1$d) : $cssFromFile_%1$d;"; private static final String CSS_PRE = CSS_IMPORT + "%n" + "addCssBlock(`"; private static final String CSS_POST = "`);"; private static final String CSS_BASIC_TPL = CSS_PRE - + "${$css_%d}" + CSS_POST; - private static final String THEMABLE_MIXIN_IMPORT = "import { css, registerStyles } from '@vaadin/vaadin-themable-mixin';"; + + "${$css_%1$d}" + CSS_POST; + private static final String THEMABLE_MIXIN_IMPORT = "import { css, unsafeCSS, registerStyles } from '@vaadin/vaadin-themable-mixin';"; private static final String REGISTER_STYLES_FOR_TEMPLATE = CSS_IMPORT + "%n" - + "registerStyles('%s', css`${$css_%d}`%s);"; + + "registerStyles('%s', $css_%1$d%s);"; private static final String IMPORT_TEMPLATE = "import '%s';"; @@ -513,13 +514,13 @@ private boolean addCssLines(Collection lines, CssData cssData, ? cssData.getThemefor() : ""; addLines(lines, String.format(REGISTER_STYLES_FOR_TEMPLATE, i, - cssImport, themeFor, i, optionals)); + cssImport, themeFor, optionals)); } else { String include = cssData.getInclude() != null ? " include=\"" + cssData.getInclude() + "\"" : ""; addLines(lines, - String.format(CSS_BASIC_TPL, i, cssImport, include, i)); + String.format(CSS_BASIC_TPL, i, cssImport, include)); } return found; } diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdateImportsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdateImportsTest.java index 3f200cb5607..adc90c169b1 100644 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdateImportsTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdateImportsTest.java @@ -122,27 +122,26 @@ public void generateImportsFile_fileContainsThemeLinesAndExpectedImportsAndCssIm expectedLines.add("import 'unresolved/component';"); expectedLines.add( - "import $css_0 from '@vaadin/vaadin-mixed-component/bar.css'"); - expectedLines.add("import $css_1 from 'Frontend/foo.css';"); - expectedLines.add("import $css_2 from 'Frontend/foo.css';"); - expectedLines.add("import $css_3 from 'Frontend/foo.css';"); - expectedLines.add("import $css_4 from 'Frontend/foo.css';"); - expectedLines.add("import $css_5 from 'Frontend/foo.css';"); - expectedLines.add("import $css_6 from 'Frontend/foo.css';"); + "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css'"); + expectedLines.add("import $cssFromFile_1 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_2 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_3 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_4 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_5 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_6 from 'Frontend/foo.css';"); expectedLines.add( - "import { css, registerStyles } from '@vaadin/vaadin-themable-mixin';"); + "import { css, unsafeCSS, registerStyles } from '@vaadin/vaadin-themable-mixin';"); expectedLines.add("addCssBlock(``);"); expectedLines.add("addCssBlock(``);"); expectedLines.add( "addCssBlock(``);"); - expectedLines - .add("registerStyles('', css`${$css_3}`, {moduleId: 'baz'});"); + expectedLines.add("registerStyles('', $css_3, {moduleId: 'baz'});"); expectedLines.add( - "registerStyles('', css`${$css_4}`, {include: 'bar', moduleId: 'baz'});"); + "registerStyles('', $css_4, {include: 'bar', moduleId: 'baz'});"); expectedLines.add( - "registerStyles('foo-bar', css`${$css_5}`, {moduleId: 'flow_css_mod'});"); + "registerStyles('foo-bar', $css_5, {moduleId: 'flow_css_mod'});"); expectedLines.add( - "registerStyles('foo-bar', css`${$css_6}`, {include: 'bar', moduleId: 'flow_css_mod'});"); + "registerStyles('foo-bar', $css_6, {include: 'bar', moduleId: 'flow_css_mod'});"); assertFalse(importsFile.exists()); diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractUpdateImportsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractUpdateImportsTest.java index ca5add6696b..021b5cd65eb 100644 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractUpdateImportsTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractUpdateImportsTest.java @@ -308,25 +308,24 @@ public void generateLines_resultingLinesContainsThemeLinesAndExpectedImportsAndC expectedLines.add("import 'unresolved/component';"); expectedLines.add( - "import $css_0 from '@vaadin/vaadin-mixed-component/bar.css';"); - expectedLines.add("import $css_1 from 'Frontend/foo.css';"); - expectedLines.add("import $css_2 from 'Frontend/foo.css';"); - expectedLines.add("import $css_3 from 'Frontend/foo.css';"); - expectedLines.add("import $css_4 from 'Frontend/foo.css';"); - expectedLines.add("import $css_5 from 'Frontend/foo.css';"); - expectedLines.add("import $css_6 from 'Frontend/foo.css';"); + "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css';"); + expectedLines.add("import $cssFromFile_1 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_2 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_3 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_4 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_5 from 'Frontend/foo.css';"); + expectedLines.add("import $cssFromFile_6 from 'Frontend/foo.css';"); expectedLines.add("addCssBlock(``);"); expectedLines.add("addCssBlock(``);"); expectedLines.add( "addCssBlock(``);"); - expectedLines - .add("registerStyles('', css`${$css_3}`, {moduleId: 'baz'});"); + expectedLines.add("registerStyles('', $css_3, {moduleId: 'baz'});"); expectedLines.add( - "registerStyles('', css`${$css_4}`, {include: 'bar', moduleId: 'baz'});"); + "registerStyles('', $css_4, {include: 'bar', moduleId: 'baz'});"); expectedLines.add( - "registerStyles('foo-bar', css`${$css_5}`, {moduleId: 'flow_css_mod'});"); + "registerStyles('foo-bar', $css_5, {moduleId: 'flow_css_mod'});"); expectedLines.add( - "registerStyles('foo-bar', css`${$css_6}`, {include: 'bar', moduleId: 'flow_css_mod'});"); + "registerStyles('foo-bar', $css_6, {include: 'bar', moduleId: 'flow_css_mod'});"); expectedLines.add("import 'generated-modules-foo';"); expectedLines.add("import 'generated-modules-bar';"); diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsTest.java index 8c486c8e8dc..ba0e514986b 100644 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsTest.java @@ -148,14 +148,14 @@ Logger log() { // Contains CSS import lines MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "import $css_0 from '@vaadin/vaadin-mixed-component/bar.css';")); + "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css';")); MatcherAssert.assertThat(mainContent, CoreMatchers .containsString("addCssBlock(``);")); - MatcherAssert.assertThat(mainContent, CoreMatchers - .containsString("import $css_5 from 'Frontend/foo.css';")); MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "registerStyles('foo-bar', css`${$css_5}`, {moduleId: 'flow_css_mod'});")); + "import $cssFromFile_5 from 'Frontend/foo.css';")); + MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( + "registerStyles('foo-bar', $css_5, {moduleId: 'flow_css_mod'});")); // Contains theme imports MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( @@ -201,17 +201,17 @@ Logger log() { // Does not contains CSS import lines MatcherAssert.assertThat(fallBackContent, CoreMatchers.not(CoreMatchers.containsString( - "import $css_0 from '@vaadin/vaadin-mixed-component/bar.css';"))); + "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css';"))); // Contain lines to import exported modules from main file MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( "export const addCssBlock = function(block, before = false) {")); // Contains CSS import lines from CP not discovered by byte scanner - MatcherAssert.assertThat(fallBackContent, CoreMatchers - .containsString("import $css_0 from 'Frontend/b-css.css';")); MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "registerStyles('extra-foo', css`${$css_2}`, {include: 'extra-bar', moduleId: 'fallback_flow_css_mod'});")); + "import $cssFromFile_0 from 'Frontend/b-css.css';")); + MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( + "registerStyles('extra-foo', $css_2, {include: 'extra-bar', moduleId: 'fallback_flow_css_mod'});")); // Does not contains JS module imports MatcherAssert.assertThat(fallBackContent, CoreMatchers.not(CoreMatchers @@ -303,10 +303,10 @@ Logger log() { // Contains CSS import lines from CP not discovered by byte // scanner - MatcherAssert.assertThat(fallBackContent, CoreMatchers - .containsString("import $css_0 from 'Frontend/foo.css';")); MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "registerStyles('', css`${$css_0}`, {include: 'bar', moduleId: 'baz'});")); + "import $cssFromFile_0 from 'Frontend/foo.css';")); + MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( + "registerStyles('', $css_0, {include: 'bar', moduleId: 'baz'});")); // Contains JS module imports MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( diff --git a/flow-tests/test-application-theme/test-theme-component-live-reload/src/main/java/com/vaadin/flow/uitest/ui/ComponentThemeLiveReloadView.java b/flow-tests/test-application-theme/test-theme-component-live-reload/src/main/java/com/vaadin/flow/uitest/ui/ComponentThemeLiveReloadView.java index e1160d0d58d..1d0cf14ed70 100644 --- a/flow-tests/test-application-theme/test-theme-component-live-reload/src/main/java/com/vaadin/flow/uitest/ui/ComponentThemeLiveReloadView.java +++ b/flow-tests/test-application-theme/test-theme-component-live-reload/src/main/java/com/vaadin/flow/uitest/ui/ComponentThemeLiveReloadView.java @@ -23,6 +23,7 @@ import com.vaadin.flow.component.html.Span; import com.vaadin.flow.router.Route; import com.vaadin.flow.uitest.servlet.ViewTestLayout; +import com.vaadin.flow.uitest.ui.dependencies.ThemableTextField; @Route(value = "com.vaadin.flow.uitest.ui.ComponentThemeLiveReloadView", layout = ViewTestLayout.class) public class ComponentThemeLiveReloadView extends Div { @@ -35,7 +36,7 @@ public class ComponentThemeLiveReloadView extends Div { private final Span attachIdLabel = new Span(); public ComponentThemeLiveReloadView() { - TestThemedTextField testThemedTextField = new TestThemedTextField(); + ThemableTextField testThemedTextField = new ThemableTextField(); testThemedTextField.withId(THEMED_COMPONENT_ID); add(testThemedTextField); diff --git a/flow-tests/test-frontend/vite-basics/frontend/cssimport-textfield.css b/flow-tests/test-frontend/vite-basics/frontend/cssimport-textfield.css new file mode 100644 index 00000000000..2348e1905fd --- /dev/null +++ b/flow-tests/test-frontend/vite-basics/frontend/cssimport-textfield.css @@ -0,0 +1,3 @@ +:host { + background: rgb(173, 216, 230); +} diff --git a/flow-tests/test-frontend/vite-basics/frontend/cssimport.css b/flow-tests/test-frontend/vite-basics/frontend/cssimport.css new file mode 100644 index 00000000000..a0e63db4a85 --- /dev/null +++ b/flow-tests/test-frontend/vite-basics/frontend/cssimport.css @@ -0,0 +1,3 @@ +body { + background: rgb(211, 211, 211); +} diff --git a/flow-tests/test-frontend/vite-basics/package.json b/flow-tests/test-frontend/vite-basics/package.json index 4446788546b..13f5406b430 100644 --- a/flow-tests/test-frontend/vite-basics/package.json +++ b/flow-tests/test-frontend/vite-basics/package.json @@ -10,13 +10,15 @@ "@vaadin/flow-frontend": "./target/flow-frontend", "@vaadin/router": "1.7.4", "@vaadin/vaadin-lumo-styles": "22.0.0-alpha9", + "@vaadin/vaadin-text-field": "22.0.0-alpha9", "construct-style-sheets-polyfill": "3.0.4", "copy-to-clipboard": "^3.3.1", - "lit": "2.0.0", + "lit": "2.1.4", "package-outside-npm": "file:package-outside-npm", "package2-outside-npm": "./package2-outside-npm" }, "devDependencies": { + "@rollup/plugin-replace": "3.1.0", "@vaadin/application-theme-plugin": "./target/plugins/application-theme-plugin", "@vaadin/build-status-plugin": "./target/plugins/build-status-plugin", "@vaadin/theme-live-reload-plugin": "./target/plugins/theme-live-reload-plugin", @@ -37,10 +39,12 @@ "@vaadin/common-frontend": "0.0.17", "@vaadin/router": "1.7.4", "@vaadin/vaadin-lumo-styles": "22.0.0-alpha9", + "@vaadin/vaadin-text-field": "22.0.0-alpha9", "construct-style-sheets-polyfill": "3.0.4", - "lit": "2.0.0" + "lit": "2.1.4" }, "devDependencies": { + "@rollup/plugin-replace": "3.1.0", "glob": "7.1.6", "mkdirp": "1.0.4", "rollup-plugin-brotli": "3.1.0", @@ -51,6 +55,30 @@ "workbox-core": "6.4.2", "workbox-precaching": "6.4.2" }, - "hash": "1fbd15f1fc5035e3b4c52bd7b61168316b3b8ea359e30c73c01d39373962b5da" + "hash": "a7eca1c52a990494443679351b12088160f1fb9f37356bbfe42416b751e63a60" + }, + "overrides": { + "@polymer/polymer": "$@polymer/polymer", + "@testscope/all": "$@testscope/all", + "@testscope/button": "$@testscope/button", + "@vaadin/bundles": "$@vaadin/bundles", + "@vaadin/common-frontend": "$@vaadin/common-frontend", + "@vaadin/router": "$@vaadin/router", + "@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles", + "construct-style-sheets-polyfill": "$construct-style-sheets-polyfill", + "copy-to-clipboard": "$copy-to-clipboard", + "lit": "$lit", + "package-outside-npm": "$package-outside-npm", + "package2-outside-npm": "$package2-outside-npm", + "glob": "$glob", + "mkdirp": "$mkdirp", + "rollup-plugin-brotli": "$rollup-plugin-brotli", + "typescript": "$typescript", + "vite": "$vite", + "vite-plugin-checker": "$vite-plugin-checker", + "workbox-build": "$workbox-build", + "workbox-core": "$workbox-core", + "workbox-precaching": "$workbox-precaching", + "@rollup/plugin-replace": "$@rollup/plugin-replace" } } diff --git a/flow-tests/test-frontend/vite-basics/src/main/java/com/vaadin/viteapp/views/empty/MainView.java b/flow-tests/test-frontend/vite-basics/src/main/java/com/vaadin/viteapp/views/empty/MainView.java index 405d0849bcd..ac14f30ae3f 100644 --- a/flow-tests/test-frontend/vite-basics/src/main/java/com/vaadin/viteapp/views/empty/MainView.java +++ b/flow-tests/test-frontend/vite-basics/src/main/java/com/vaadin/viteapp/views/empty/MainView.java @@ -1,10 +1,9 @@ package com.vaadin.viteapp.views.empty; import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Html; import com.vaadin.flow.component.HtmlComponent; import com.vaadin.flow.component.UI; +import com.vaadin.flow.component.dependency.CssImport; import com.vaadin.flow.component.dependency.JsModule; import com.vaadin.flow.component.html.Div; import com.vaadin.flow.component.html.H2; @@ -12,12 +11,15 @@ import com.vaadin.flow.component.html.NativeButton; import com.vaadin.flow.component.html.Paragraph; import com.vaadin.flow.router.Route; +import com.vaadin.flow.uitest.ui.dependencies.ThemableTextField; @Route("") @JsModule("./jsonloader.js") @JsModule("package-outside-npm/index.js") @JsModule("package2-outside-npm/index.js") @JsModule("./testscopebuttonloader.js") +@CssImport(value = "./cssimport-textfield.css", themeFor = "vaadin-text-field") +@CssImport(value = "./cssimport.css") public class MainView extends Div { public static final String LOAD_AND_SHOW_JSON = "loadAndShowJson"; @@ -75,6 +77,9 @@ public MainView() { add(outsideStatus); add(new HtmlComponent("testscope-button")); + ThemableTextField textField = new ThemableTextField(); + textField.setId("themedfield"); + add(textField); } } diff --git a/flow-tests/test-frontend/vite-basics/src/test/java/com/vaadin/viteapp/ThemeIT.java b/flow-tests/test-frontend/vite-basics/src/test/java/com/vaadin/viteapp/ThemeIT.java index 398cc7967a2..b1723cac803 100644 --- a/flow-tests/test-frontend/vite-basics/src/test/java/com/vaadin/viteapp/ThemeIT.java +++ b/flow-tests/test-frontend/vite-basics/src/test/java/com/vaadin/viteapp/ThemeIT.java @@ -24,4 +24,18 @@ public void themeStylesShouldNotBeAddedToHead() { Assert.assertEquals("Theme rule should not have been added to ", 0, styleTagsWithString.size()); } + + @Test + public void cssImportAnnotation() { + String bodyBackground = (String) executeScript( + "return getComputedStyle(document.body).backgroundColor"); + Assert.assertEquals("rgb(211, 211, 211)", bodyBackground); + } + + @Test + public void cssImportAnnotationForComponent() { + String fieldBackground = (String) executeScript( + "return getComputedStyle(document.querySelector('#themedfield')).backgroundColor"); + Assert.assertEquals("rgb(173, 216, 230)", fieldBackground); + } } diff --git a/flow-tests/test-frontend/vite-test-assets/pom.xml b/flow-tests/test-frontend/vite-test-assets/pom.xml index a58e4876528..9ecb0cfe69c 100644 --- a/flow-tests/test-frontend/vite-test-assets/pom.xml +++ b/flow-tests/test-frontend/vite-test-assets/pom.xml @@ -59,6 +59,11 @@ com.vaadin flow-html-components-testbench + + com.vaadin + flow-test-resources + ${project.version} + com.vaadin addon-with-templates diff --git a/flow-tests/test-application-theme/test-theme-component-live-reload/src/main/java/com/vaadin/flow/uitest/ui/TestThemedTextField.java b/flow-tests/test-resources/src/main/java/com/vaadin/flow/uitest/ui/dependencies/ThemableTextField.java similarity index 83% rename from flow-tests/test-application-theme/test-theme-component-live-reload/src/main/java/com/vaadin/flow/uitest/ui/TestThemedTextField.java rename to flow-tests/test-resources/src/main/java/com/vaadin/flow/uitest/ui/dependencies/ThemableTextField.java index 89145e685d8..ec56d8b8ad3 100644 --- a/flow-tests/test-application-theme/test-theme-component-live-reload/src/main/java/com/vaadin/flow/uitest/ui/TestThemedTextField.java +++ b/flow-tests/test-resources/src/main/java/com/vaadin/flow/uitest/ui/dependencies/ThemableTextField.java @@ -13,22 +13,20 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.flow.uitest.ui; +package com.vaadin.flow.uitest.ui.dependencies; import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Tag; import com.vaadin.flow.component.dependency.JsModule; import com.vaadin.flow.component.dependency.NpmPackage; -import com.vaadin.flow.uitest.ui.dependencies.TestVersion; - /** - * Custom vaadin text field for testing component theming live reload. + * Custom vaadin text field for testing component theming. */ @JsModule("@vaadin/vaadin-text-field/vaadin-text-field.js") @Tag("vaadin-text-field") @NpmPackage(value = "@vaadin/vaadin-text-field", version = TestVersion.VAADIN) -public class TestThemedTextField extends Component { +public class ThemableTextField extends Component { /** * Set the component id.