@ui5/builder 3.0.0-alpha.2 → 3.0.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,10 +2,37 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
4
4
 
5
- A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.2...HEAD).
5
+ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.5...HEAD).
6
+
7
+ <a name="v3.0.0-alpha.5"></a>
8
+ ## [v3.0.0-alpha.5] - 2022-04-14
9
+ ### Bug Fixes
10
+ - **LibraryBuilder:** Align task order of "generateComponentPreload" [`aea061d`](https://github.com/SAP/ui5-builder/commit/aea061d9d6c2ac0c11484dcc08bdcda23ab62986)
11
+
12
+ ### Features
13
+ - **generateThemeDesignerResources task:** Create css_variables.less ([#730](https://github.com/SAP/ui5-builder/issues/730)) [`34e69be`](https://github.com/SAP/ui5-builder/commit/34e69be95fc8ec1961b24b7e2580c2c993d814d3)
14
+
15
+ ### BREAKING CHANGE
16
+
17
+ For library projects, the task "generateComponentPreload" is now
18
+ executed after tasks "generateLibraryManifest" and
19
+ "generateManifestBundle" instead of before them.
20
+
21
+
22
+ <a name="v3.0.0-alpha.4"></a>
23
+ ## [v3.0.0-alpha.4] - 2022-04-05
24
+ ### Features
25
+ - **builder:** Add cssVariables option ([#728](https://github.com/SAP/ui5-builder/issues/728)) [`30d58e1`](https://github.com/SAP/ui5-builder/commit/30d58e1081c1bdc665f13952ecbe5c400b5f4ed7)
26
+
27
+
28
+ <a name="v3.0.0-alpha.3"></a>
29
+ ## [v3.0.0-alpha.3] - 2022-03-10
30
+ ### Bug Fixes
31
+ - **LocatorResourcePool:** Wait for resources in prepare step ([#719](https://github.com/SAP/ui5-builder/issues/719)) [`1b7f93f`](https://github.com/SAP/ui5-builder/commit/1b7f93f4988340d7a6575be3191a02e6c295ebd0)
32
+
6
33
 
7
34
  <a name="v3.0.0-alpha.2"></a>
8
- ## [v3.0.0-alpha.2] - 2022-02-21
35
+ ## [v3.0.0-alpha.2] - 2022-02-25
9
36
  ### Bug Fixes
10
37
  - **XMLTemplateAnalyzer:** Analyze core:require of FragmentDefinition [`af075ed`](https://github.com/SAP/ui5-builder/commit/af075edf784d9f1ba162a34f0bf150dbcbc0f479)
11
38
 
@@ -687,6 +714,9 @@ to load the custom bundle file instead.
687
714
  - Add ability to configure component preloads and custom bundles [`2241e5f`](https://github.com/SAP/ui5-builder/commit/2241e5ff98fd95f1f80cc74959655ae7a9c660e7)
688
715
 
689
716
 
717
+ [v3.0.0-alpha.5]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.4...v3.0.0-alpha.5
718
+ [v3.0.0-alpha.4]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.3...v3.0.0-alpha.4
719
+ [v3.0.0-alpha.3]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.2...v3.0.0-alpha.3
690
720
  [v3.0.0-alpha.2]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.1...v3.0.0-alpha.2
691
721
  [v3.0.0-alpha.1]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.0...v3.0.0-alpha.1
692
722
  [v3.0.0-alpha.0]: https://github.com/SAP/ui5-builder/compare/v2.11.2...v3.0.0-alpha.0
@@ -15,22 +15,26 @@ const GLOBAL_TAGS = Object.freeze({
15
15
  * @memberof module:@ui5/builder.builder
16
16
  */
17
17
  class BuildContext {
18
- constructor({rootProject}) {
18
+ constructor({rootProject, options = {}}) {
19
19
  if (!rootProject) {
20
20
  throw new Error(`Missing parameter 'rootProject'`);
21
21
  }
22
22
  this.rootProject = rootProject;
23
23
  this.projectBuildContexts = [];
24
-
25
24
  this._resourceTagCollection = new ResourceTagCollection({
26
25
  allowedTags: Object.values(GLOBAL_TAGS)
27
26
  });
27
+ this.options = options;
28
28
  }
29
29
 
30
30
  getRootProject() {
31
31
  return this.rootProject;
32
32
  }
33
33
 
34
+ getOption(key) {
35
+ return this.options[key];
36
+ }
37
+
34
38
  createProjectContext({project, resources}) {
35
39
  const projectBuildContext = new ProjectBuildContext({
36
40
  buildContext: this,
@@ -39,6 +39,10 @@ class ProjectBuildContext {
39
39
  return this._project === this._buildContext.getRootProject();
40
40
  }
41
41
 
42
+ getOption(key) {
43
+ return this._buildContext.getOption(key);
44
+ }
45
+
42
46
  registerCleanupTask(callback) {
43
47
  this.queues.cleanup.push(callback);
44
48
  }
@@ -224,6 +224,7 @@ module.exports = {
224
224
  * @param {boolean} [parameters.dev=false]
225
225
  * Decides whether a development build should be activated (skips non-essential and time-intensive tasks)
226
226
  * @param {boolean} [parameters.selfContained=false] Flag to activate self contained build
227
+ * @param {boolean} [parameters.cssVariables=false] Flag to activate CSS variables generation
227
228
  * @param {boolean} [parameters.jsdoc=false] Flag to activate JSDoc build
228
229
  * @param {Array.<string>} [parameters.includedTasks=[]] List of tasks to be included
229
230
  * @param {Array.<string>} [parameters.excludedTasks=[]] List of tasks to be excluded.
@@ -234,7 +235,7 @@ module.exports = {
234
235
  async build({
235
236
  tree, destPath, cleanDest = false,
236
237
  buildDependencies = false, includedDependencies = [], excludedDependencies = [],
237
- dev = false, selfContained = false, jsdoc = false,
238
+ dev = false, selfContained = false, cssVariables = false, jsdoc = false,
238
239
  includedTasks = [], excludedTasks = [], devExcludeProject = []
239
240
  }) {
240
241
  const startTime = process.hrtime();
@@ -249,7 +250,12 @@ module.exports = {
249
250
  virBasePath: "/"
250
251
  });
251
252
 
252
- const buildContext = new BuildContext({rootProject: tree});
253
+ const buildContext = new BuildContext({
254
+ rootProject: tree,
255
+ options: {
256
+ cssVariables: cssVariables
257
+ }
258
+ });
253
259
  const cleanupSigHooks = registerCleanupSigHooks(buildContext);
254
260
 
255
261
  const projects = {}; // Unique project index to prevent building the same project multiple times
@@ -1,9 +1,5 @@
1
1
  const Resource = require("./Resource");
2
2
 
3
- // function extractName(path) {
4
- // return path.slice( "/resources/".length);
5
- // }
6
-
7
3
  class LocatorResource extends Resource {
8
4
  constructor(pool, resource, moduleName) {
9
5
  super(pool, moduleName, null, resource.getStatInfo());
@@ -10,7 +10,7 @@ class LocatorResourcePool extends ResourcePool {
10
10
  if (!moduleName) {
11
11
  moduleName = resource.getPath().slice("/resources/".length);
12
12
  }
13
- this.addResource(new LocatorResource(this, resource, moduleName));
13
+ return this.addResource(new LocatorResource(this, resource, moduleName));
14
14
  }).filter(Boolean)
15
15
  );
16
16
  }
@@ -90,8 +90,7 @@ const log = require("@ui5/logger").getLogger("builder:processors:bundlers:module
90
90
  * @public
91
91
  * @typedef {object} ModuleBundleOptions
92
92
  * @property {boolean} [optimize=true] Whether the module bundle gets minified
93
- * @property {boolean} [sourceMap] Whether to generate a source map file for the bundle.
94
- * Defaults to true if <code>optimize</code> is set to true
93
+ * @property {boolean} [sourceMap=true] Whether to generate a source map file for the bundle
95
94
  * @property {boolean} [decorateBootstrapModule=false] If set to 'false', the module won't be decorated
96
95
  * with an optimization marker
97
96
  * @property {boolean} [addTryCatchRestartWrapper=false] Whether to wrap bootable module bundles with
@@ -124,12 +123,14 @@ const log = require("@ui5/logger").getLogger("builder:processors:bundlers:module
124
123
  Optional mapping of resource paths to module name in order to overwrite the default determination
125
124
  * @param {ModuleBundleDefinition} parameters.options.bundleDefinition Module bundle definition
126
125
  * @param {ModuleBundleOptions} [parameters.options.bundleOptions] Module bundle options
127
- * @returns {Promise<module:@ui5/builder.processors.MinifierResult[]>} Promise resolving with module bundle resources
126
+ * @returns {Promise<module:@ui5/builder.processors.ModuleBundlerResult[]>}
127
+ * Promise resolving with module bundle resources
128
128
  */
129
129
  module.exports = function({resources, options: {bundleDefinition, bundleOptions, moduleNameMapping}}) {
130
130
  // Apply defaults without modifying the passed object
131
131
  bundleOptions = Object.assign({}, {
132
132
  optimize: true,
133
+ sourceMap: true,
133
134
  decorateBootstrapModule: false,
134
135
  addTryCatchRestartWrapper: false,
135
136
  usePredefineCalls: false,
@@ -34,12 +34,13 @@ const debugFileRegex = /((?:\.view|\.fragment|\.controller|\.designtime|\.suppor
34
34
  * @alias module:@ui5/builder.processors.minifier
35
35
  * @param {object} parameters Parameters
36
36
  * @param {module:@ui5/fs.Resource[]} parameters.resources List of resources to be processed
37
- * @param {boolean} [parameters.addSourceMappingUrl=true]
37
+ * @param {object} [parameters.options] Options
38
+ * @param {boolean} [parameters.options.addSourceMappingUrl=true]
38
39
  * Whether to add a sourceMappingURL reference to the end of the minified resource
39
40
  * @returns {Promise<module:@ui5/builder.processors.MinifierResult[]>}
40
41
  * Promise resolving with object of resource, dbgResource and sourceMap
41
42
  */
42
- module.exports = async function({resources, addSourceMappingUrl = true}) {
43
+ module.exports = async function({resources, options: {addSourceMappingUrl = true} = {}}) {
43
44
  return Promise.all(resources.map(async (resource) => {
44
45
  const dbgPath = resource.getPath().replace(debugFileRegex, "-dbg$1");
45
46
  const dbgResource = await resource.clone();
@@ -108,6 +108,18 @@ class TaskUtil {
108
108
  return this._projectBuildContext.isRootProject();
109
109
  }
110
110
 
111
+ /**
112
+ * Retrieves a build option defined by its <code>key</code.
113
+ * If no option with the given <code>key</code> is stored, <code>undefined</code> is returned.
114
+ *
115
+ * @param {string} key The option key
116
+ * @returns {any|undefined} The build option (or undefined)
117
+ * @private
118
+ */
119
+ getBuildOption(key) {
120
+ return this._projectBuildContext.getOption(key);
121
+ }
122
+
111
123
  /**
112
124
  * Register a function that must be executed once the build is finished. This can be used to, for example,
113
125
  * clean up files temporarily created on the file system. If the callback returns a Promise, it will be waited for.
@@ -1,5 +1,5 @@
1
1
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
2
- const ModuleName = require("../../lbt/utils/ModuleName");
2
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
3
3
  const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
4
4
 
5
5
  /**
@@ -21,7 +21,7 @@ module.exports = function({
21
21
  workspace, dependencies, taskUtil, options: {projectName, bundleDefinition, bundleOptions}
22
22
  }) {
23
23
  let combo = new ReaderCollectionPrioritized({
24
- name: `libraryBundler - prioritize workspace over dependencies: ${projectName}`,
24
+ name: `generateBundle - prioritize workspace over dependencies: ${projectName}`,
25
25
  readers: [workspace, dependencies]
26
26
  });
27
27
 
@@ -82,34 +82,16 @@ module.exports = function({
82
82
  }
83
83
 
84
84
  return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
85
- const moduleNameMapping = {};
85
+ const options = {bundleDefinition, bundleOptions};
86
86
  if (!optimize && taskUtil) {
87
- // For "unoptimized" bundles, the non-debug files have already been filtered out above.
88
- // Now we need to create a mapping from the debug-variant resource path to the respective module name,
89
- // which is basically the non-debug resource path, minus the "/resources/"" prefix.
90
- // This mapping overwrites internal logic of the LocatorResourcePool which would otherwise determine
91
- // the module name from the resource path, which would contain "-dbg" in this case. That would be
92
- // incorrect since debug-variants should still keep the original module name.
93
- for (let i = resources.length - 1; i >= 0; i--) {
94
- const resourcePath = resources[i].getPath();
95
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
96
- const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
97
- if (!nonDbgPath) {
98
- throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
99
- }
100
- moduleNameMapping[resourcePath] = nonDbgPath.slice("/resources/".length);
101
- }
102
- }
87
+ options.moduleNameMapping = createModuleNameMapping({resources, taskUtil});
103
88
  }
104
- return moduleBundler({
105
- options: {
106
- bundleDefinition,
107
- bundleOptions,
108
- moduleNameMapping
109
- },
110
- resources
111
- }).then((bundles) => {
112
- return Promise.all(bundles.map(({bundle, sourceMap}) => {
89
+ return moduleBundler({options, resources}).then((bundles) => {
90
+ return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
91
+ if (!bundle) {
92
+ // Skip empty bundles
93
+ return;
94
+ }
113
95
  if (taskUtil) {
114
96
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
115
97
  if (sourceMap) {
@@ -2,7 +2,7 @@ const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateLib
2
2
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
3
3
  const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
4
4
  const {negateFilters} = require("../../lbt/resources/ResourceFilterList");
5
- const ModuleName = require("../../lbt/utils/ModuleName");
5
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
6
6
 
7
7
  function getDefaultLibraryPreloadFilters(namespace, excludes) {
8
8
  const filters = [
@@ -311,7 +311,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
311
311
  return resource.getPath() === "/resources/ui5loader.js";
312
312
  });
313
313
 
314
- const unoptimizedModuleNameMapping = {};
314
+ let unoptimizedModuleNameMapping;
315
315
  let unoptimizedResources = resources;
316
316
  if (taskUtil) {
317
317
  unoptimizedResources = await new ReaderCollectionPrioritized({
@@ -322,22 +322,10 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
322
322
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
323
323
  }).byGlob("/**/*.{js,json,xml,html,properties,library,js.map}");
324
324
 
325
- // For "unoptimized" bundles, the non-debug files have already been filtered out above.
326
- // Now we need to create a mapping from the debug-variant resource path to the respective module
327
- // name, which is basically the non-debug resource path, minus the "/resources/"" prefix.
328
- // This mapping overwrites internal logic of the LocatorResourcePool which would otherwise determine
329
- // the module name from the resource path, which would contain "-dbg" in this case. That would be
330
- // incorrect since debug-variants should still keep the original module name.
331
- for (let i = unoptimizedResources.length - 1; i >= 0; i--) {
332
- const resourcePath = unoptimizedResources[i].getPath();
333
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
334
- const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
335
- if (!nonDbgPath) {
336
- throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
337
- }
338
- unoptimizedModuleNameMapping[resourcePath] = nonDbgPath.slice("/resources/".length);
339
- }
340
- }
325
+ unoptimizedModuleNameMapping = createModuleNameMapping({
326
+ resources: unoptimizedResources,
327
+ taskUtil
328
+ });
341
329
  }
342
330
 
343
331
  let filters;
@@ -1,7 +1,7 @@
1
1
  const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateStandaloneAppBundle");
2
2
  const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
3
3
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
4
- const ModuleName = require("../../lbt/utils/ModuleName");
4
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
5
5
 
6
6
  function getBundleDefinition(config) {
7
7
  const bundleDefinition = {
@@ -101,7 +101,7 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
101
101
  filters = ["jquery.sap.global.js"];
102
102
  }
103
103
 
104
- const unoptimizedModuleNameMapping = {};
104
+ let unoptimizedModuleNameMapping;
105
105
  let unoptimizedResources = resources;
106
106
  if (taskUtil) {
107
107
  unoptimizedResources = await new ReaderCollectionPrioritized({
@@ -112,22 +112,10 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
112
112
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
113
113
  }).byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}");
114
114
 
115
- // For "unoptimized" bundles, the non-debug files have already been filtered out above.
116
- // Now we need to create a mapping from the debug-variant resource path to the respective module name,
117
- // which is basically the non-debug resource path, minus the "/resources/"" prefix.
118
- // This mapping overwrites internal logic of the LocatorResourcePool which would otherwise determine
119
- // the module name from the resource path, which would contain "-dbg" in this case. That would be
120
- // incorrect since debug-variants should still keep the original module name.
121
- for (let i = unoptimizedResources.length - 1; i >= 0; i--) {
122
- const resourcePath = unoptimizedResources[i].getPath();
123
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
124
- const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
125
- if (!nonDbgPath) {
126
- throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
127
- }
128
- unoptimizedModuleNameMapping[resourcePath] = nonDbgPath.slice("/resources/".length);
129
- }
130
- }
115
+ unoptimizedModuleNameMapping = createModuleNameMapping({
116
+ resources: unoptimizedResources,
117
+ taskUtil
118
+ });
131
119
  }
132
120
 
133
121
  await Promise.all([
@@ -0,0 +1,30 @@
1
+ const ModuleName = require("../../../lbt/utils/ModuleName");
2
+
3
+ /**
4
+ * For "unoptimized" bundles, the non-debug files have already been filtered out above.
5
+ * Now we need to create a mapping from the debug-variant resource path to the respective module
6
+ * name, which is basically the non-debug resource path, minus the "/resources/"" prefix.
7
+ * This mapping overwrites internal logic of the LocatorResourcePool which would otherwise determine
8
+ * the module name from the resource path, which would contain "-dbg" in this case. That would be
9
+ * incorrect since debug-variants should still keep the original module name.
10
+ *
11
+ * @private
12
+ * @param {object} parameters Parameters
13
+ * @param {module:@ui5/fs.Resource[]} parameters.resources List of resources
14
+ * @param {module:@ui5/builder.tasks.TaskUtil|object} parameters.taskUtil TaskUtil
15
+ * @returns {object} Module name mapping
16
+ */
17
+ module.exports = function({resources, taskUtil}) {
18
+ const moduleNameMapping = {};
19
+ for (let i = resources.length - 1; i >= 0; i--) {
20
+ const resourcePath = resources[i].getPath();
21
+ if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
22
+ const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
23
+ if (!nonDbgPath) {
24
+ throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
25
+ }
26
+ moduleNameMapping[resourcePath] = nonDbgPath.slice("/resources/".length);
27
+ }
28
+ }
29
+ return moduleNameMapping;
30
+ };
@@ -3,6 +3,37 @@ const log = require("@ui5/logger").getLogger("builder:tasks:generateThemeDesigne
3
3
  const libraryLessGenerator = require("../processors/libraryLessGenerator");
4
4
  const {ReaderCollectionPrioritized, Resource, fsInterface} = require("@ui5/fs");
5
5
 
6
+ /**
7
+ * Returns a relative path from the given themeFolder to the root namespace.
8
+ *
9
+ * When combining the given themeFolder with the returned relative path it
10
+ * resolves to "/resources/". However the "/resources/" part is not important
11
+ * here as it doesn't exist within the theming engine environment where the
12
+ * UI5 resources are part of a "UI5" folder (e.g. "UI5/sap/ui/core/") that
13
+ * is next to a "Base" folder.
14
+ *
15
+ * @example
16
+ * getPathToRoot("/resources/sap/ui/foo/themes/base")
17
+ * > "../../../../../"
18
+ *
19
+ * @param {string} themeFolder Virtual path including /resources/
20
+ * @returns {string} Relative path to root namespace
21
+ */
22
+ function getPathToRoot(themeFolder) {
23
+ // -2 for initial "/"" and "resources/"
24
+ return "../".repeat(themeFolder.split("/").length - 2);
25
+ }
26
+
27
+ /**
28
+ * Generates an less import statement for the given <code>filePath</code>
29
+ *
30
+ * @param {string} filePath The path to the desired file
31
+ * @returns {string} The less import statement
32
+ */
33
+ function lessImport(filePath) {
34
+ return `@import "${filePath}";\n`;
35
+ }
36
+
6
37
  function generateLibraryDotTheming({namespace, version, hasThemes}) {
7
38
  const dotTheming = {
8
39
  sEntity: "Library",
@@ -80,6 +111,82 @@ async function generateThemeDotTheming({workspace, combo, themeFolder}) {
80
111
  return newDotThemingResource;
81
112
  }
82
113
 
114
+ async function createCssVariablesLessResource({workspace, combo, themeFolder}) {
115
+ const pathToRoot = getPathToRoot(themeFolder);
116
+ const cssVariablesSourceLessFile = "css_variables.source.less";
117
+ const cssVariablesLessFile = "css_variables.less";
118
+
119
+ // posix as it is a virtual path (separated with /)
120
+ const themeName = posixPath.basename(themeFolder);
121
+ // The "base" theme of the baseLib is called "baseTheme"
122
+ const baseLibThemeName = themeName === "base" ? "baseTheme" : themeName;
123
+
124
+ // Some themes do not have a base.less file (e.g. sap_hcb)
125
+ const hasBaseLess = !!(await combo.byPath(`/resources/sap/ui/core/themes/${themeName}/base.less`));
126
+
127
+ let cssVariablesLess =
128
+ `/* NOTE: This file was generated as an optimized version of "${cssVariablesSourceLessFile}" \
129
+ for the Theme Designer. */\n\n`;
130
+
131
+ if (themeName !== "base") {
132
+ const cssVariablesSourceLessResource = await workspace.byPath(
133
+ posixPath.join(themeFolder, cssVariablesSourceLessFile)
134
+ );
135
+
136
+ if (!cssVariablesSourceLessResource) {
137
+ throw new Error(`Could not find file "${cssVariablesSourceLessFile}" in theme "${themeFolder}"`);
138
+ }
139
+
140
+ const cssVariablesSourceLess = await cssVariablesSourceLessResource.getString();
141
+
142
+ cssVariablesLess += lessImport(`../base/${cssVariablesLessFile}`);
143
+ cssVariablesLess += `
144
+ /* START "${cssVariablesSourceLessFile}" */
145
+ ${cssVariablesSourceLess}
146
+ /* END "${cssVariablesSourceLessFile}" */
147
+
148
+ `;
149
+ }
150
+
151
+ if (hasBaseLess) {
152
+ cssVariablesLess += lessImport(`${pathToRoot}../Base/baseLib/${baseLibThemeName}/base.less`);
153
+ }
154
+ cssVariablesLess += lessImport(`${pathToRoot}sap/ui/core/themes/${themeName}/global.less`);
155
+
156
+ return new Resource({
157
+ path: posixPath.join(themeFolder, cssVariablesLessFile),
158
+ string: cssVariablesLess
159
+ });
160
+ }
161
+
162
+ async function generateCssVariablesLess({workspace, combo, namespace}) {
163
+ let cssVariablesSourceLessResourcePattern;
164
+ if (namespace) {
165
+ // In case of a library only check for themes directly below the namespace
166
+ cssVariablesSourceLessResourcePattern = `/resources/${namespace}/themes/*/css_variables.source.less`;
167
+ } else {
168
+ // In case of a theme-library check for all "themes"
169
+ cssVariablesSourceLessResourcePattern = `/resources/**/themes/*/css_variables.source.less`;
170
+ }
171
+
172
+ const cssVariablesSourceLessResource = await workspace.byGlob(cssVariablesSourceLessResourcePattern);
173
+
174
+ const hasCssVariables = cssVariablesSourceLessResource.length > 0;
175
+
176
+ if (hasCssVariables) {
177
+ await Promise.all(
178
+ cssVariablesSourceLessResource.map(async (cssVariableSourceLess) => {
179
+ const themeFolder = posixPath.dirname(cssVariableSourceLess.getPath());
180
+ log.verbose(`Generating css_variables.less for theme ${themeFolder}`);
181
+ const r = await createCssVariablesLessResource({
182
+ workspace, combo, themeFolder
183
+ });
184
+ return await workspace.write(r);
185
+ })
186
+ );
187
+ }
188
+ }
189
+
83
190
  /**
84
191
  * Generates resources required for integration with the SAP Theme Designer.
85
192
  *
@@ -163,4 +270,7 @@ module.exports = async function({workspace, dependencies, options: {projectName,
163
270
  await Promise.all(
164
271
  libraryLessResources.map((resource) => workspace.write(resource))
165
272
  );
273
+
274
+ // css_variables.less
275
+ await generateCssVariablesLess({workspace, combo, namespace});
166
276
  };
@@ -18,7 +18,9 @@ module.exports = async function({workspace, taskUtil, options: {pattern, omitSou
18
18
  const resources = await workspace.byGlob(pattern);
19
19
  const processedResources = await minifier({
20
20
  resources,
21
- addSourceMappingUrl: !omitSourceMapResources
21
+ options: {
22
+ addSourceMappingUrl: !omitSourceMapResources
23
+ }
22
24
  });
23
25
 
24
26
  return Promise.all(processedResources.map(async ({resource, dbgResource, sourceMapResource}) => {
@@ -43,6 +43,27 @@ class ApplicationBuilder extends AbstractBuilder {
43
43
  });
44
44
  });
45
45
 
46
+ // Support rules should not be minified to have readable code in the Support Assistant
47
+ const minificationPattern = ["/**/*.js", "!**/*.support.js"];
48
+ if (["2.6"].includes(project.specVersion)) {
49
+ const minificationExcludes = project.builder && project.builder.minification &&
50
+ project.builder.minification.excludes;
51
+ if (minificationExcludes) {
52
+ // TODO 3.0: namespaces should become mandatory, see existing check above
53
+ const patternPrefix = project.metadata.namespace ? "/resources/" : "/";
54
+ this.enhancePatternWithExcludes(minificationPattern, minificationExcludes, patternPrefix);
55
+ }
56
+ }
57
+ this.addTask("minify", async () => {
58
+ return getTask("minify").task({
59
+ workspace: resourceCollections.workspace,
60
+ taskUtil,
61
+ options: {
62
+ pattern: minificationPattern
63
+ }
64
+ });
65
+ });
66
+
46
67
  this.addTask("generateFlexChangesBundle", async () => {
47
68
  const generateFlexChangesBundle = getTask("generateFlexChangesBundle").task;
48
69
  return generateFlexChangesBundle({
@@ -67,27 +88,6 @@ class ApplicationBuilder extends AbstractBuilder {
67
88
  });
68
89
  }
69
90
 
70
- // Support rules should not be minified to have readable code in the Support Assistant
71
- const minificationPattern = ["/**/*.js", "!**/*.support.js"];
72
- if (["2.6"].includes(project.specVersion)) {
73
- const minificationExcludes = project.builder && project.builder.minification &&
74
- project.builder.minification.excludes;
75
- if (minificationExcludes) {
76
- // TODO 3.0: namespaces should become mandatory, see existing check above
77
- const patternPrefix = project.metadata.namespace ? "/resources/" : "/";
78
- this.enhancePatternWithExcludes(minificationPattern, minificationExcludes, patternPrefix);
79
- }
80
- }
81
- this.addTask("minify", async () => {
82
- return getTask("minify").task({
83
- workspace: resourceCollections.workspace,
84
- taskUtil,
85
- options: {
86
- pattern: minificationPattern
87
- }
88
- });
89
- });
90
-
91
91
  const componentPreload = project.builder && project.builder.componentPreload;
92
92
  if (componentPreload && (componentPreload.namespaces || componentPreload.paths)) {
93
93
  this.addTask("generateComponentPreload", async () => {
@@ -38,7 +38,7 @@ class LibraryBuilder extends AbstractBuilder {
38
38
  workspace: resourceCollections.workspace,
39
39
  options: {
40
40
  version: project.version,
41
- pattern: "/**/*.{js,json,library,less,theme,html}"
41
+ pattern: "/**/*.{js,json,library,css,less,theme,html}"
42
42
  }
43
43
  });
44
44
  });
@@ -109,23 +109,6 @@ class LibraryBuilder extends AbstractBuilder {
109
109
  });
110
110
  });
111
111
 
112
- const componentPreload = project.builder && project.builder.componentPreload;
113
- if (componentPreload) {
114
- this.addTask("generateComponentPreload", async () => {
115
- return getTask("generateComponentPreload").task({
116
- workspace: resourceCollections.workspace,
117
- dependencies: resourceCollections.dependencies,
118
- taskUtil,
119
- options: {
120
- projectName: project.metadata.name,
121
- paths: componentPreload.paths,
122
- namespaces: componentPreload.namespaces,
123
- excludes: componentPreload.excludes
124
- }
125
- });
126
- });
127
- }
128
-
129
112
  this.addTask("generateLibraryManifest", async () => {
130
113
  return getTask("generateLibraryManifest").task({
131
114
  workspace: resourceCollections.workspace,
@@ -150,6 +133,23 @@ class LibraryBuilder extends AbstractBuilder {
150
133
  });
151
134
  }
152
135
 
136
+ const componentPreload = project.builder && project.builder.componentPreload;
137
+ if (componentPreload) {
138
+ this.addTask("generateComponentPreload", async () => {
139
+ return getTask("generateComponentPreload").task({
140
+ workspace: resourceCollections.workspace,
141
+ dependencies: resourceCollections.dependencies,
142
+ taskUtil,
143
+ options: {
144
+ projectName: project.metadata.name,
145
+ paths: componentPreload.paths,
146
+ namespaces: componentPreload.namespaces,
147
+ excludes: componentPreload.excludes
148
+ }
149
+ });
150
+ });
151
+ }
152
+
153
153
  this.addTask("generateLibraryPreload", async () => {
154
154
  return getTask("generateLibraryPreload").task({
155
155
  workspace: resourceCollections.workspace,
@@ -198,7 +198,8 @@ class LibraryBuilder extends AbstractBuilder {
198
198
  projectName: project.metadata.name,
199
199
  librariesPattern: !taskUtil.isRootProject() ? "/resources/**/(*.library|library.js)" : undefined,
200
200
  themesPattern: !taskUtil.isRootProject() ? "/resources/sap/ui/core/themes/*" : undefined,
201
- inputPattern
201
+ inputPattern,
202
+ cssVariables: taskUtil.getBuildOption("cssVariables")
202
203
  }
203
204
  });
204
205
  });
@@ -31,7 +31,8 @@ class ThemeLibraryBuilder extends AbstractBuilder {
31
31
  projectName: project.metadata.name,
32
32
  librariesPattern: !taskUtil.isRootProject() ? "/resources/**/(*.library|library.js)" : undefined,
33
33
  themesPattern: !taskUtil.isRootProject() ? "/resources/sap/ui/core/themes/*" : undefined,
34
- inputPattern: "/resources/**/themes/*/library.source.less"
34
+ inputPattern: "/resources/**/themes/*/library.source.less",
35
+ cssVariables: taskUtil.getBuildOption("cssVariables")
35
36
  }
36
37
  });
37
38
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/builder",
3
- "version": "3.0.0-alpha.2",
3
+ "version": "3.0.0-alpha.5",
4
4
  "description": "UI5 Tooling - Builder",
5
5
  "author": {
6
6
  "name": "SAP SE",