diff --git a/lib/builder/BuildContext.js b/lib/builder/BuildContext.js index 0f61271a7..656a86de9 100644 --- a/lib/builder/BuildContext.js +++ b/lib/builder/BuildContext.js @@ -7,18 +7,27 @@ const ProjectBuildContext = require("./ProjectBuildContext"); * @memberof module:@ui5/builder.builder */ class BuildContext { - constructor({rootProject}) { + constructor({rootProject, options = {}}) { if (!rootProject) { throw new Error(`Missing parameter 'rootProject'`); } this.rootProject = rootProject; this.projectBuildContexts = []; + this.options = options; } getRootProject() { return this.rootProject; } + getOptions() { + return this.options; + } + + getOption(key) { + return this.options[key]; + } + createProjectContext({project, resources}) { const projectBuildContext = new ProjectBuildContext({ buildContext: this, diff --git a/lib/builder/ProjectBuildContext.js b/lib/builder/ProjectBuildContext.js index a9dbf9c54..1877efb37 100644 --- a/lib/builder/ProjectBuildContext.js +++ b/lib/builder/ProjectBuildContext.js @@ -37,6 +37,14 @@ class ProjectBuildContext { return this._project === this._buildContext.getRootProject(); } + getOptions() { + this._buildContext.getOptions(); + } + + getOption(key) { + this._buildContext.getOption(key); + } + registerCleanupTask(callback) { this.queues.cleanup.push(callback); } diff --git a/lib/builder/builder.js b/lib/builder/builder.js index cb81de584..786114500 100644 --- a/lib/builder/builder.js +++ b/lib/builder/builder.js @@ -225,6 +225,7 @@ module.exports = { * @param {boolean} [parameters.dev=false] * Decides whether a development build should be activated (skips non-essential and time-intensive tasks) * @param {boolean} [parameters.selfContained=false] Flag to activate self contained build + * @param {boolean} [parameters.cssVariables=false] Flag to activate CSS variables generation * @param {boolean} [parameters.jsdoc=false] Flag to activate JSDoc build * @param {Array.} [parameters.includedTasks=[]] List of tasks to be included * @param {Array.} [parameters.excludedTasks=[]] List of tasks to be excluded. @@ -235,7 +236,7 @@ module.exports = { async build({ tree, destPath, cleanDest = false, buildDependencies = false, includedDependencies = [], excludedDependencies = [], - dev = false, selfContained = false, jsdoc = false, + dev = false, selfContained = false, cssVariables = false, jsdoc = false, includedTasks = [], excludedTasks = [], devExcludeProject = [] }) { const startTime = process.hrtime(); @@ -250,7 +251,12 @@ module.exports = { virBasePath: "/" }); - const buildContext = new BuildContext({rootProject: tree}); + const buildContext = new BuildContext({ + rootProject: tree, + options: { + cssVariables: cssVariables + } + }); const cleanupSigHooks = registerCleanupSigHooks(buildContext); const projects = {}; // Unique project index to prevent building the same project multiple times diff --git a/lib/tasks/TaskUtil.js b/lib/tasks/TaskUtil.js index 0420d1b39..b36290c84 100644 --- a/lib/tasks/TaskUtil.js +++ b/lib/tasks/TaskUtil.js @@ -108,6 +108,28 @@ class TaskUtil { return this._projectBuildContext.isRootProject(); } + /** + * Retrieves all build options. If not a single option is stored, an empty object is returned. + * + * @returns {object} The built options + * @public + */ + getBuildOptions() { + return this._projectBuildContext.getOptions(); + } + + /** + * Retrieves a build option defined by it's keykey is stored, undefined is returned. + * + * @param {string} key The option key + * @returns {object} The built options + * @public + */ + getBuildOption(key) { + return this._projectBuildContext.getOption(key); + } + /** * Register a function that must be executed once the build is finished. This can be used to, for example, * clean up files temporarily created on the file system. If the callback returns a Promise, it will be waited for. diff --git a/lib/types/library/LibraryBuilder.js b/lib/types/library/LibraryBuilder.js index 90149a18f..4c98f9918 100644 --- a/lib/types/library/LibraryBuilder.js +++ b/lib/types/library/LibraryBuilder.js @@ -178,7 +178,8 @@ class LibraryBuilder extends AbstractBuilder { projectName: project.metadata.name, librariesPattern: !taskUtil.isRootProject() ? "/resources/**/(*.library|library.js)" : undefined, themesPattern: !taskUtil.isRootProject() ? "/resources/sap/ui/core/themes/*" : undefined, - inputPattern + inputPattern, + cssVariables: taskUtil.getBuildOption("cssVariables") } }); }); diff --git a/lib/types/themeLibrary/ThemeLibraryBuilder.js b/lib/types/themeLibrary/ThemeLibraryBuilder.js index 2f49912af..a5a760e6f 100644 --- a/lib/types/themeLibrary/ThemeLibraryBuilder.js +++ b/lib/types/themeLibrary/ThemeLibraryBuilder.js @@ -31,7 +31,8 @@ class ThemeLibraryBuilder extends AbstractBuilder { projectName: project.metadata.name, librariesPattern: !taskUtil.isRootProject() ? "/resources/**/(*.library|library.js)" : undefined, themesPattern: !taskUtil.isRootProject() ? "/resources/sap/ui/core/themes/*" : undefined, - inputPattern: "/resources/**/themes/*/library.source.less" + inputPattern: "/resources/**/themes/*/library.source.less", + cssVariables: taskUtil.getBuildOption("cssVariables") } }); }); diff --git a/test/lib/builder/BuildContext.js b/test/lib/builder/BuildContext.js index 1021fce32..5b5d79753 100644 --- a/test/lib/builder/BuildContext.js +++ b/test/lib/builder/BuildContext.js @@ -25,6 +25,42 @@ test("getRootProject", (t) => { t.is(buildContext.getRootProject(), "pony", "Returned correct value"); }); +test("getBuildOption", (t) => { + const buildContext = new BuildContext({ + rootProject: "root_project", + options: { + a: true, + b: "Pony", + c: 235, + d: { + d1: "Bee" + } + } + }); + + t.is(buildContext.getOption("a"), true, "Returned 'boolean' value is correct"); + t.is(buildContext.getOption("b"), "Pony", "Returned 'String' value is correct"); + t.is(buildContext.getOption("c"), 235, "Returned 'Number' value is correct"); + t.deepEqual(buildContext.getOption("d"), {d1: "Bee"}, "Returned 'object' value is correct"); +}); + +test("getBuildOptions", (t) => { + const options = { + a: true, + b: "Pony", + c: 235, + d: { + d1: "Bee" + } + }; + const buildContext = new BuildContext({ + rootProject: "root_project", + options: options + }); + + t.deepEqual(buildContext.getOptions(), options, "Returned value is correct"); +}); + test.serial("createProjectContext", (t) => { class DummyProjectContext { constructor({buildContext, project, resources}) { diff --git a/test/lib/builder/builder.js b/test/lib/builder/builder.js index b40fa6d45..3bc833602 100644 --- a/test/lib/builder/builder.js +++ b/test/lib/builder/builder.js @@ -111,9 +111,13 @@ test.serial("Build", async (t) => { getTag: getTagStub }); const isRootProjectStub = sinon.stub().returns(true); + const getOptionsStub = sinon.stub().returns({friend: "Pony"}); + const getOptionStub = sinon.stub().returns("Pony"); const dummyProjectContext = { getResourceTagCollection: getResourceTagCollectionStub, isRootProject: isRootProjectStub, + getOptions: getOptionsStub, + getOption: getOptionStub, STANDARD_TAGS: { OmitFromBuildResult: "👻" } @@ -888,6 +892,22 @@ test.serial("Build library.coreBuildtime: replaceBuildtime", (t) => { }); }); +// test.serial("Build library with theme configured for CSS variables", (t) => { +// return builder.build({ +// cssVariables: true +// }).then(() => { +// assert.ok(false); +// }); +// }); + +// test.serial("Build theme-library with CSS variables", (t) => { +// return builder.build({ +// cssVariables: true +// }).then(() => { +// assert.ok(false); +// }); +// }); + test.serial("Cleanup", async (t) => { const BuildContext = require("../../../lib/builder/BuildContext"); const createProjectContextStub = sinon.spy(BuildContext.prototype, "createProjectContext"); diff --git a/test/lib/tasks/TaskUtil.js b/test/lib/tasks/TaskUtil.js index 5f2aba82c..66ca4deb0 100644 --- a/test/lib/tasks/TaskUtil.js +++ b/test/lib/tasks/TaskUtil.js @@ -93,6 +93,39 @@ test("isRootProject", async (t) => { t.is(res, true, "Correct result"); }); +test("getBuildOption", (t) => { + const getOptionStub = sinon.stub().returns("Pony"); + const taskUtil = new TaskUtil({ + projectBuildContext: { + STANDARD_TAGS: ["some tag"], + getOption: getOptionStub + } + }); + + const res = taskUtil.getBuildOption("friend"); + + t.is(getOptionStub.callCount, 1, "ProjectBuildContext#getBuildOption got called once"); + t.is(res, "Pony", "Correct result"); +}); + +test("getBuildOptions", (t) => { + const expectedResult = { + friend: "Pony" + }; + const getOptionsStub = sinon.stub().returns(expectedResult); + const taskUtil = new TaskUtil({ + projectBuildContext: { + STANDARD_TAGS: ["some tag"], + getOptions: getOptionsStub + } + }); + + const res = taskUtil.getBuildOptions(); + + t.is(getOptionsStub.callCount, 1, "ProjectBuildContext#getBuildOptions got called once"); + t.deepEqual(res, expectedResult, "Correct result"); +}); + test("registerCleanupTask", async (t) => { const registerCleanupTaskStub = sinon.stub(); const taskUtil = new TaskUtil({ diff --git a/test/lib/types/themeLibrary/ThemeLibraryBuilder.js b/test/lib/types/themeLibrary/ThemeLibraryBuilder.js index 7deab2f94..b3bdb0f55 100644 --- a/test/lib/types/themeLibrary/ThemeLibraryBuilder.js +++ b/test/lib/types/themeLibrary/ThemeLibraryBuilder.js @@ -39,6 +39,12 @@ test("tasks", async (t) => { taskUtil: { isRootProject: () => { return true; + }, + getBuildOptions: () => { + return {}; + }, + getBuildOption: (key) => { + return key; } } });