Skip to content

Commit

Permalink
fix: Move generated theme files to frontend/generated (#11370)
Browse files Browse the repository at this point in the history
Any theme file that is generated is
now generated into `frontend/generated`
Add missing readme documentation for plugins

Fixes #11180
  • Loading branch information
caalador authored Jul 6, 2021
1 parent bf662a8 commit 61d964a
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 61 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ flow-tests/**/types.d.ts
package.json
package-lock.json
/flow-tests/**/*.generated.js
/flow-tests/**/frontend/generated/
20 changes: 10 additions & 10 deletions drivers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,35 @@
<root>
<windows>
<driver id="googlechrome">
<version id="89.0.4389.23">
<version id="91.0.4472.19">
<bitrate thirtytwobit="true" sixtyfourbit="true">
<filelocation>https://chromedriver.storage.googleapis.com/89.0.4389.23/chromedriver_win32.zip</filelocation>
<hash>9ac62a6bcdb49627a2839e5cbb312d8fe7c340e3</hash>
<filelocation>https://chromedriver.storage.googleapis.com/91.0.4472.19/chromedriver_win32.zip</filelocation>
<hash>ff66f571ffc16745badf0de3fd5474a54ba126ad</hash>
<hashtype>sha1</hashtype>
</bitrate>
</version>
</driver>
</windows>
<linux>
<driver id="googlechrome">
<version id="89.0.4389.23">
<version id="91.0.4472.19">
<bitrate sixtyfourbit="true">
<filelocation>https://chromedriver.storage.googleapis.com/89.0.4389.23/chromedriver_linux64.zip</filelocation>
<hash>b6db711b7ceb4655dc61df3ff7bd89b4b1647f81</hash>
<filelocation>https://chromedriver.storage.googleapis.com/91.0.4472.19/chromedriver_linux64.zip</filelocation>
<hash>ef30bc45922ccaefba075cec2b71bd96e61415c7</hash>
<hashtype>sha1</hashtype>
</bitrate>
</version>
</driver>
</linux>
<osx>
<driver id="googlechrome">
<version id="89.0.4389.23">
<version id="91.0.4472.19">
<bitrate sixtyfourbit="true">
<filelocation>https://chromedriver.storage.googleapis.com/89.0.4389.23/chromedriver_mac64.zip</filelocation>
<hash>b0857b123b956317ed5a858bac400a6d9ad01f8c</hash>
<filelocation>https://chromedriver.storage.googleapis.com/91.0.4472.19/chromedriver_mac64.zip</filelocation>
<hash>7cb6549ff48a04bfb4e64a512ffdbf22e59fdc87</hash>
<hashtype>sha1</hashtype>
</bitrate>
</version>
</driver>
</osx>
</root>
</root>
35 changes: 35 additions & 0 deletions flow-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,38 @@ then add the plugin with required options to `plugins` in the generated file
}),
]
```

### Logs from plugins and loaders

To set logging for the plugins one can add to the `webpack.config.js`
file:
```js
{
stats: {
logging: 'log'
}
}
```

where the accepted logging levels are:
- 'none', false - disable logging
- 'error' - errors only
- 'warn' - errors and warnings only
- 'info' - errors, warnings, and info messages
- 'log', true - errors, warnings, info messages, log messages, groups, clears. Collapsed groups are displayed in a collapsed state.
- 'verbose' - log everything except debug and trace. Collapsed groups are displayed in expanded state.

For debug level logs one should have the settings as:

```js
{
stats: {
logging: 'log',
loggingDebug: [
'theme-loader',
'ApplicationThemePlugin',
'FlowIdPlugin'
]
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ protected Collection<String> getThemeLines() {

if (hasApplicationTheme) {
// If we define a theme name we need to import
// theme/theme-generated.js
// theme/theme.js
lines.add(
"import {applyTheme} from 'themes/theme-generated.js';");
"import {applyTheme} from 'generated/theme.js';");
lines.add("applyTheme(document);");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -29,12 +30,16 @@
import com.vaadin.flow.theme.ThemeDefinition;

import static com.vaadin.flow.server.Constants.APPLICATION_THEME_ROOT;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_FRONTEND_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_GENERATED_DIR;

/**
* Task for generating the theme-generated.js file for importing application
* Task for generating the theme.js file for importing application
* theme.
* <p>
* Generated file is generated into <code>./frontend/generated</code>
*
* @since
*/
Expand All @@ -50,11 +55,10 @@ public class TaskUpdateThemeImport implements FallibleCommand {

TaskUpdateThemeImport(File npmFolder, ThemeDefinition theme,
File frontendDirectory) {
File generatedDir = new File(npmFolder,
System.getProperty(PARAM_GENERATED_DIR, DEFAULT_GENERATED_DIR));
this.themeImportFile = new File(
new File(generatedDir, APPLICATION_THEME_ROOT),
"theme-generated.js");
File generatedDir = new File(new File(npmFolder.getAbsolutePath(),
System.getProperty(PARAM_FRONTEND_DIR, DEFAULT_FRONTEND_DIR)),
"generated");
this.themeImportFile = new File(generatedDir, "theme.js");
this.theme = theme;
this.frontendDirectory = frontendDirectory;
this.npmFolder = npmFolder;
Expand All @@ -80,9 +84,9 @@ public void execute() throws ExecutionFailedException {

try {
FileUtils.write(themeImportFile, String.format(
"import {applyTheme as _applyTheme} from 'themes/%s/%s.generated.js';%n"
"import {applyTheme as _applyTheme} from 'generated/theme-%s.generated.js';%n"
+ "export const applyTheme = _applyTheme;%n",
theme.getName(), theme.getName()), StandardCharsets.UTF_8);
theme.getName()), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new ExecutionFailedException(
"Unable to write theme import file", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static Map<String, String> getReplacementsMap(String tag,

if (themeName != null && !themeName.isEmpty()) {
replacements.put("ThemeImport",
"import {applyTheme} from 'themes/theme-generated.js';\n\n");
"import {applyTheme} from 'generated/theme.js';\n\n");
replacements.put("ApplyTheme", "applyTheme(shadow);\n ");
} else {
replacements.put("ThemeImport", "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class ApplicationThemePlugin {
if (!this.options.themeProjectFolders) {
throw new Error("Missing themeProjectFolders path array");
}
if (!this.options.frontendGeneratedFolder) {
throw new Error("Missing frontendGeneratedFolder path");
}
}

apply(compiler) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
],
"repository": "vaadin/flow",
"name": "@vaadin/application-theme-plugin",
"version": "0.4.0",
"version": "0.4.1",
"main": "application-theme-plugin.js",
"author": "Vaadin Ltd",
"license": "Apache-2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function generateThemeFile(themeFolder, themeName, themeProperties, productionMo
}

if (themeProperties.parent) {
themeFile += `import {applyTheme as applyBaseTheme} from 'themes/${themeProperties.parent}/${themeProperties.parent}.generated.js';`;
themeFile += `import {applyTheme as applyBaseTheme} from './theme-${themeProperties.parent}.generated.js';`;
}

themeFile += createLinkReferences;
Expand Down Expand Up @@ -164,7 +164,7 @@ function generateThemeFile(themeFolder, themeName, themeProperties, productionMo
// styles.css will always be available as we write one if it doesn't exist.
let filename = path.basename(styles);
let variable = camelCase(filename);
imports.push(`import ${variable} from './${filename}';\n`);
imports.push(`import ${variable} from 'themes/${themeName}/${filename}';\n`);

/* Lumo must be first so that custom styles override Lumo styles */
const lumoImports = themeProperties.lumoImports || ["color", "typography"];
Expand Down Expand Up @@ -193,7 +193,7 @@ function generateThemeFile(themeFolder, themeName, themeProperties, productionMo
if (fs.existsSync(document)) {
filename = path.basename(document);
variable = camelCase(filename);
imports.push(`import ${variable} from './${filename}';\n`);
imports.push(`import ${variable} from 'themes/${themeName}/${filename}';\n`);
globalCssCode.push(`injectGlobalCss(${variable}.toString(), document);\n `);
}

Expand Down Expand Up @@ -237,7 +237,7 @@ function generateThemeFile(themeFolder, themeName, themeProperties, productionMo
const tag = filename.replace('.css', '');
const variable = camelCase(filename);
imports.push(
`import ${variable} from './${themeComponentsFolder}/${filename}';\n`
`import ${variable} from 'themes/${themeName}/${themeComponentsFolder}/${filename}';\n`
);
// Don't format as the generated file formatting will get wonky!
const componentString = `registerStyles(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ const path = require('path');
const generateThemeFile = require('./theme-generator');
const {copyStaticAssets, copyThemeResources} = require('./theme-copy');

// matches theme folder name in 'themes/my-theme/my-theme.generated.js'
const nameRegex = /themes\/(.*)\/\1.generated.js/;
// matches theme name 'my-theme' in 'generated/theme-my-theme.generated.js'
const nameRegex = /theme-(.*).generated.js/;

let prevThemeName = undefined;
let firstThemeName = undefined;
Expand All @@ -40,7 +40,7 @@ let firstThemeName = undefined;
* @param logger application theme plugin logger
*/
function processThemeResources(options, logger) {
const themeName = extractThemeName(options.themeResourceFolder);
const themeName = extractThemeName(options.frontendGeneratedFolder);
if (themeName) {
if (!prevThemeName && !firstThemeName) {
firstThemeName = themeName;
Expand Down Expand Up @@ -152,7 +152,7 @@ function handleThemes(themeName, themesFolder, options, logger) {
copyThemeResources(themeFolder, options.projectStaticAssetsOutputFolder, logger);
const themeFile = generateThemeFile(themeFolder, themeName, themeProperties, !options.devMode);

fs.writeFileSync(path.resolve(themeFolder, themeName + '.generated.js'), themeFile);
fs.writeFileSync(path.resolve(options.frontendGeneratedFolder, 'theme-' + themeName + '.generated.js'), themeFile);
return true;
}
return false;
Expand All @@ -171,22 +171,22 @@ function getThemeProperties(themeFolder) {
}

/**
* Extracts current theme name from 'theme-generated.js' file located on a
* Extracts current theme name from 'theme.js' file located on a
* given folder.
* @param themeFolder theme folder where flow generates 'theme-generated.js'
* @param frontendGeneratedFolder theme folder where flow generates 'theme.js'
* file and copies local and jar resource frontend files
* @returns {string} current theme name
*/
function extractThemeName(themeFolder) {
if (!themeFolder) {
throw new Error("Couldn't extract theme name from 'theme-generated.js'," +
function extractThemeName(frontendGeneratedFolder) {
if (!frontendGeneratedFolder) {
throw new Error("Couldn't extract theme name from 'theme.js'," +
" because the path to folder containing this file is empty. Please set" +
" the a correct folder path in ApplicationThemePlugin constructor" +
" parameters.");
}
const generatedThemeFile = path.resolve(themeFolder, "theme-generated.js");
const generatedThemeFile = path.resolve(frontendGeneratedFolder, "theme.js");
if (fs.existsSync(generatedThemeFile)) {
// read theme name from the theme-generated.js as there we always mark the used theme for webpack to handle.
// read theme name from the theme.js as there we always mark the used theme for webpack to handle.
const themeName = nameRegex.exec(fs.readFileSync(generatedThemeFile, {encoding: 'utf8'}))[1];
if (!themeName) {
throw new Error("Couldn't parse theme name from '" + generatedThemeFile + "'.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class ThemeLiveReloadPlugin {
// styles and theme generated file in one run to not have webpack
// compile error
if (deletedComponentStyleFile && !themeGeneratedFileDeleted) {
const themeGeneratedPath = "./frontend/themes/" + themeName + "/" + themeName + ".generated.js";
const themeGeneratedPath = "./frontend/generated/theme-" + themeName + ".generated.js";

logger.warn("Custom theme component style sheet '" + deletedComponentStyleFile + "' has been deleted.\n\n" +
"You should also delete '" + themeGeneratedPath + "' (simultaneously) with the component stylesheet'.\n" +
Expand Down
10 changes: 6 additions & 4 deletions flow-server/src/main/resources/webpack.generated.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,22 @@ if (watchDogPort) {
}

const flowFrontendThemesFolder = path.resolve(flowFrontendFolder, 'themes');
const frontendGeneratedFolder = path.resolve(frontendFolder, "generated");
const themeOptions = {
devMode: devMode,
// The following matches target/frontend/themes/theme-generated.js
// The following matches ./frontend/generated/theme.js
// and for theme in JAR that is copied to target/frontend/themes/
themeResourceFolder: flowFrontendThemesFolder,
themeProjectFolders: themeProjectFolders,
projectStaticAssetsOutputFolder: projectStaticAssetsOutputFolder,
frontendGeneratedFolder: frontendGeneratedFolder
};
let themeName = undefined;
let themeWatchFolders = undefined;
if (devMode) {
// Current theme name is being extracted from theme-generated.js located in
// target/frontend/themes folder
themeName = extractThemeName(flowFrontendThemesFolder);
// Current theme name is being extracted from theme.js located in
// frontend/generated folder
themeName = extractThemeName(frontendGeneratedFolder);
const parentThemePaths = findParentThemes(themeName, themeOptions);
const currentThemeFolders = [...projectStaticAssetsFolders
.map((folder) => path.resolve(folder, "themes", themeName)),
Expand Down
Loading

0 comments on commit 61d964a

Please sign in to comment.