Skip to content

Commit

Permalink
[FEATURE] Theme Build: Add compress option to minify output (#295)
Browse files Browse the repository at this point in the history
  • Loading branch information
matz3 authored Aug 1, 2019
1 parent fccb514 commit eea10ba
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 44 deletions.
16 changes: 12 additions & 4 deletions lib/processors/themeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ class ThemeBuilder {
*
* @public
* @param {module:@ui5/fs.Resource[]} resources Library files
* @param {Object} [options] Build options
* @param {boolean} [options.compress=false] Compress build output (CSS / JSON)
* @returns {Promise<module:@ui5/fs.Resource[]>} Resolving with array of created files
*/
build(resources) {
build(resources, {compress = false} = {}) {
const files = [];

const compile = (resource) => {
Expand All @@ -46,6 +48,9 @@ class ThemeBuilder {
lessInputPath: resource.getPath(),
library: {
name: libraryName
},
compiler: {
compress
}
}).then((result) => {
const themeDir = path.dirname(resource.getPath());
Expand All @@ -62,7 +67,7 @@ class ThemeBuilder {

const libParams = new Resource({
path: themeDir + "/library-parameters.json",
string: JSON.stringify(result.variables, null, "\t")
string: JSON.stringify(result.variables, null, compress ? null : "\t")
});

files.push(libCss, libCssRtl, libParams);
Expand Down Expand Up @@ -93,11 +98,14 @@ class ThemeBuilder {
* @param {Object} parameters Parameters
* @param {module:@ui5/fs.Resource[]} parameters.resources List of <code>library.source.less</code> resources to be processed
* @param {fs|module:@ui5/fs.fsInterface} parameters.fs Node fs or custom [fs interface]{@link module:resources/module:@ui5/fs.fsInterface}
* @param {Object} [parameters.options] Options
* @param {Object} [parameters.options.compress=false] Compress build output (CSS / JSON)
* @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving with theme resources
*/
module.exports = ({resources, fs}) => {
module.exports = ({resources, fs, options}) => {
const themeBuilder = new ThemeBuilder({fs});
return themeBuilder.build(resources).then((files) => {
const compress = options && options.compress;
return themeBuilder.build(resources, {compress}).then((files) => {
themeBuilder.clearCache();
return files;
});
Expand Down
5 changes: 4 additions & 1 deletion lib/tasks/buildThemes.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ module.exports = function({workspace, dependencies, options}) {
}).then((resources) => {
return themeBuilder({
resources,
fs: fsInterface(combo)
fs: fsInterface(combo),
options: {
compress: true
}
});
}).then((processedResources) => {
return Promise.all(processedResources.map((resource) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.someClass{color:black}
.someClass {
color: @someColor
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
.someClass {
color: #000000;
}

.someClass{color:#000}
/* Inline theming parameters */
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%7D')}
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%22someColor%22%3A%22%23000%22%7D')}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{}
{"someColor":"#000"}
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
.someClass {
color: #000000;
}

.someClass{color:#000}
/* Inline theming parameters */
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%7D')}
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%22someColor%22%3A%22%23000%22%7D')}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
@someColor: black;
@import "Button.less";
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.someClass{color:black}
.someClass {
color: @someColor
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
@someColor: black;
@import "Button.less";
208 changes: 208 additions & 0 deletions test/lib/processors/themeBuilder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
const test = require("ava");

const resourceFactory = require("@ui5/fs").resourceFactory;
const fsInterface = require("@ui5/fs").fsInterface;

const themeBuilderProcessor = require("../../../lib/processors/themeBuilder");
const ThemeBuilder = require("../../../lib/processors/themeBuilder").ThemeBuilder;

function prepareResources({library} = {}) {
const input =
`@someColor: black;
.someClass {
color: @someColor;
padding: 1px 2px 3px 4px;
}`;

const memoryAdapter = resourceFactory.createAdapter({
virBasePath: "/"
});

let lessFilePath;
if (library === false) {
lessFilePath = "/resources/foo.less";
} else {
lessFilePath = "/resources/sap/ui/foo/themes/base/library.source.less";
}

const resource = resourceFactory.createResource({
path: lessFilePath,
string: input
});

memoryAdapter.write(resource);

return {
resource,
memoryAdapter
};
}

function getExpectedResults({compress, library}) {
let css; let cssRtl; let json;
if (compress) {
css =
`.someClass{color:#000;padding:1px 2px 3px 4px}`;

cssRtl =
`.someClass{color:#000;padding:1px 4px 3px 2px}`;
json = `{"someColor":"#000"}`;
} else {
css =
`.someClass {
color: #000000;
padding: 1px 2px 3px 4px;
}
`;

cssRtl =
`.someClass {
color: #000000;
padding: 1px 4px 3px 2px;
}
`;

json =
`{
"someColor": "#000000"
}`;
}

if (library !== false) {
css +=
`
/* Inline theming parameters */
#sap-ui-theme-sap\\.ui\\.foo{background-image:url('data:text/plain;utf-8,%7B%22someColor%22%3A%22%23${compress ? "000" : "000000"}%22%7D')}
`;
cssRtl +=
`
/* Inline theming parameters */
#sap-ui-theme-sap\\.ui\\.foo{background-image:url('data:text/plain;utf-8,%7B%22someColor%22%3A%22%23${compress ? "000" : "000000"}%22%7D')}
`;
}

return {css, cssRtl, json};
}

test("Processor: Builds a less file (default options)", async (t) => {
const {resource, memoryAdapter} = prepareResources();

const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
resources: [resource],
fs: fsInterface(memoryAdapter)
});

const expected = getExpectedResults({compress: false});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});

test("Processor: Builds a less file (compress = true)", async (t) => {
const {resource, memoryAdapter} = prepareResources();

const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
resources: [resource],
fs: fsInterface(memoryAdapter),
options: {
compress: true
}
});

const expected = getExpectedResults({compress: true});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});

test("Processor: Builds a less file (compress = false)", async (t) => {
const {resource, memoryAdapter} = prepareResources();

const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
resources: [resource],
fs: fsInterface(memoryAdapter),
options: {
compress: false
}
});

const expected = getExpectedResults({compress: false});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});

test("Processor: Builds a less file (no library)", async (t) => {
const {resource, memoryAdapter} = prepareResources({library: false});

const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
resources: [resource],
fs: fsInterface(memoryAdapter),
options: {
compress: false
}
});

const expected = getExpectedResults({compress: false, library: false});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});

test("ThemeBuilder: Builds a less file", async (t) => {
const {resource, memoryAdapter} = prepareResources();

const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});

const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource]);

const expected = getExpectedResults({compress: false});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});

test("ThemeBuilder: Builds a less file (compress = true)", async (t) => {
const {resource, memoryAdapter} = prepareResources();

const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});

const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource], {
compress: true
});

const expected = getExpectedResults({compress: true});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});

test("ThemeBuilder: Builds a less file (compress = false)", async (t) => {
const {resource, memoryAdapter} = prepareResources();

const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});

const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource], {
compress: false
});

const expected = getExpectedResults({compress: false});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});

test("ThemeBuilder: Builds a less file (no library)", async (t) => {
const {resource, memoryAdapter} = prepareResources({library: false});

const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});

const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource], {
compress: false
});

const expected = getExpectedResults({compress: false, library: false});
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
});
32 changes: 6 additions & 26 deletions test/lib/tasks/buildThemes.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,17 @@ test("integration: simple", (t) => {
padding: 1px 2px 3px 4px;
}`;
const cssExpected =
`.fluffyHammer {
color: #123456;
padding: 1px 2px 3px 4px;
}
`.fluffyHammer{color:#123456;padding:1px 2px 3px 4px}
/* Inline theming parameters */
#sap-ui-theme-super\\.duper\\.looper{background-image:url('data:text/plain;utf-8,%7B%22deepSea%22%3A%22%23123456%22%7D')}
`;
const cssRtlExpected =
`.fluffyHammer {
color: #123456;
padding: 1px 4px 3px 2px;
}
`.fluffyHammer{color:#123456;padding:1px 4px 3px 2px}
/* Inline theming parameters */
#sap-ui-theme-super\\.duper\\.looper{background-image:url('data:text/plain;utf-8,%7B%22deepSea%22%3A%22%23123456%22%7D')}
`;
const parametersExpected =
`{
"deepSea": "#123456"
}`;
`{"deepSea":"#123456"}`;
const lessPath = "/resources/super/duper/looper/themes/brightlight/library.source.less";
const cssPath = "/resources/super/duper/looper/themes/brightlight/library.css";
const cssRtlPath = "/resources/super/duper/looper/themes/brightlight/library-RTL.css";
Expand Down Expand Up @@ -106,27 +96,17 @@ test("integration: imports", (t) => {
const lessVariablesContent =
"@deepSea: #123456;";
const cssExpected =
`.fluffyHammer {
color: #123456;
padding: 1px 2px 3px 4px;
}
`.fluffyHammer{color:#123456;padding:1px 2px 3px 4px}
/* Inline theming parameters */
#sap-ui-theme-super\\.duper\\.looper{background-image:url('data:text/plain;utf-8,%7B%22deepSea%22%3A%22%23123456%22%7D')}
`;
const cssRtlExpected =
`.fluffyHammer {
color: #123456;
padding: 1px 4px 3px 2px;
}
`.fluffyHammer{color:#123456;padding:1px 4px 3px 2px}
/* Inline theming parameters */
#sap-ui-theme-super\\.duper\\.looper{background-image:url('data:text/plain;utf-8,%7B%22deepSea%22%3A%22%23123456%22%7D')}
`;
const parametersExpected =
`{
"deepSea": "#123456"
}`;
`{"deepSea":"#123456"}`;
const lessPath = "/resources/super/duper/looper/themes/brightlight/library.source.less";
const lessVariablesPath = "/resources/super/duper/looper/themes/brightlight/variables.less";
const cssPath = "/resources/super/duper/looper/themes/brightlight/library.css";
Expand Down

0 comments on commit eea10ba

Please sign in to comment.