Skip to content

Commit eea10ba

Browse files
authored
[FEATURE] Theme Build: Add compress option to minify output (#295)
1 parent fccb514 commit eea10ba

File tree

11 files changed

+243
-44
lines changed

11 files changed

+243
-44
lines changed

lib/processors/themeBuilder.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ class ThemeBuilder {
2828
*
2929
* @public
3030
* @param {module:@ui5/fs.Resource[]} resources Library files
31+
* @param {Object} [options] Build options
32+
* @param {boolean} [options.compress=false] Compress build output (CSS / JSON)
3133
* @returns {Promise<module:@ui5/fs.Resource[]>} Resolving with array of created files
3234
*/
33-
build(resources) {
35+
build(resources, {compress = false} = {}) {
3436
const files = [];
3537

3638
const compile = (resource) => {
@@ -46,6 +48,9 @@ class ThemeBuilder {
4648
lessInputPath: resource.getPath(),
4749
library: {
4850
name: libraryName
51+
},
52+
compiler: {
53+
compress
4954
}
5055
}).then((result) => {
5156
const themeDir = path.dirname(resource.getPath());
@@ -62,7 +67,7 @@ class ThemeBuilder {
6267

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

6873
files.push(libCss, libCssRtl, libParams);
@@ -93,11 +98,14 @@ class ThemeBuilder {
9398
* @param {Object} parameters Parameters
9499
* @param {module:@ui5/fs.Resource[]} parameters.resources List of <code>library.source.less</code> resources to be processed
95100
* @param {fs|module:@ui5/fs.fsInterface} parameters.fs Node fs or custom [fs interface]{@link module:resources/module:@ui5/fs.fsInterface}
101+
* @param {Object} [parameters.options] Options
102+
* @param {Object} [parameters.options.compress=false] Compress build output (CSS / JSON)
96103
* @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving with theme resources
97104
*/
98-
module.exports = ({resources, fs}) => {
105+
module.exports = ({resources, fs, options}) => {
99106
const themeBuilder = new ThemeBuilder({fs});
100-
return themeBuilder.build(resources).then((files) => {
107+
const compress = options && options.compress;
108+
return themeBuilder.build(resources, {compress}).then((files) => {
101109
themeBuilder.clearCache();
102110
return files;
103111
});

lib/tasks/buildThemes.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ module.exports = function({workspace, dependencies, options}) {
5353
}).then((resources) => {
5454
return themeBuilder({
5555
resources,
56-
fs: fsInterface(combo)
56+
fs: fsInterface(combo),
57+
options: {
58+
compress: true
59+
}
5760
});
5861
}).then((processedResources) => {
5962
return Promise.all(processedResources.map((resource) => {
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
.someClass{color:black}
1+
.someClass {
2+
color: @someColor
3+
}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
.someClass {
2-
color: #000000;
3-
}
4-
1+
.someClass{color:#000}
52
/* Inline theming parameters */
6-
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%7D')}
3+
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%22someColor%22%3A%22%23000%22%7D')}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{}
1+
{"someColor":"#000"}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
.someClass {
2-
color: #000000;
3-
}
4-
1+
.someClass{color:#000}
52
/* Inline theming parameters */
6-
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%7D')}
3+
#sap-ui-theme-theme\.j{background-image:url('data:text/plain;utf-8,%7B%22someColor%22%3A%22%23000%22%7D')}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
@someColor: black;
12
@import "Button.less";
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
.someClass{color:black}
1+
.someClass {
2+
color: @someColor
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
@someColor: black;
12
@import "Button.less";

test/lib/processors/themeBuilder.js

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
const test = require("ava");
2+
3+
const resourceFactory = require("@ui5/fs").resourceFactory;
4+
const fsInterface = require("@ui5/fs").fsInterface;
5+
6+
const themeBuilderProcessor = require("../../../lib/processors/themeBuilder");
7+
const ThemeBuilder = require("../../../lib/processors/themeBuilder").ThemeBuilder;
8+
9+
function prepareResources({library} = {}) {
10+
const input =
11+
`@someColor: black;
12+
.someClass {
13+
color: @someColor;
14+
padding: 1px 2px 3px 4px;
15+
}`;
16+
17+
const memoryAdapter = resourceFactory.createAdapter({
18+
virBasePath: "/"
19+
});
20+
21+
let lessFilePath;
22+
if (library === false) {
23+
lessFilePath = "/resources/foo.less";
24+
} else {
25+
lessFilePath = "/resources/sap/ui/foo/themes/base/library.source.less";
26+
}
27+
28+
const resource = resourceFactory.createResource({
29+
path: lessFilePath,
30+
string: input
31+
});
32+
33+
memoryAdapter.write(resource);
34+
35+
return {
36+
resource,
37+
memoryAdapter
38+
};
39+
}
40+
41+
function getExpectedResults({compress, library}) {
42+
let css; let cssRtl; let json;
43+
if (compress) {
44+
css =
45+
`.someClass{color:#000;padding:1px 2px 3px 4px}`;
46+
47+
cssRtl =
48+
`.someClass{color:#000;padding:1px 4px 3px 2px}`;
49+
json = `{"someColor":"#000"}`;
50+
} else {
51+
css =
52+
`.someClass {
53+
color: #000000;
54+
padding: 1px 2px 3px 4px;
55+
}
56+
`;
57+
58+
cssRtl =
59+
`.someClass {
60+
color: #000000;
61+
padding: 1px 4px 3px 2px;
62+
}
63+
`;
64+
65+
json =
66+
`{
67+
"someColor": "#000000"
68+
}`;
69+
}
70+
71+
if (library !== false) {
72+
css +=
73+
`
74+
/* Inline theming parameters */
75+
#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')}
76+
`;
77+
cssRtl +=
78+
`
79+
/* Inline theming parameters */
80+
#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')}
81+
`;
82+
}
83+
84+
return {css, cssRtl, json};
85+
}
86+
87+
test("Processor: Builds a less file (default options)", async (t) => {
88+
const {resource, memoryAdapter} = prepareResources();
89+
90+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
91+
resources: [resource],
92+
fs: fsInterface(memoryAdapter)
93+
});
94+
95+
const expected = getExpectedResults({compress: false});
96+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
97+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
98+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
99+
});
100+
101+
test("Processor: Builds a less file (compress = true)", async (t) => {
102+
const {resource, memoryAdapter} = prepareResources();
103+
104+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
105+
resources: [resource],
106+
fs: fsInterface(memoryAdapter),
107+
options: {
108+
compress: true
109+
}
110+
});
111+
112+
const expected = getExpectedResults({compress: true});
113+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
114+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
115+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
116+
});
117+
118+
test("Processor: Builds a less file (compress = false)", async (t) => {
119+
const {resource, memoryAdapter} = prepareResources();
120+
121+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
122+
resources: [resource],
123+
fs: fsInterface(memoryAdapter),
124+
options: {
125+
compress: false
126+
}
127+
});
128+
129+
const expected = getExpectedResults({compress: false});
130+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
131+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
132+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
133+
});
134+
135+
test("Processor: Builds a less file (no library)", async (t) => {
136+
const {resource, memoryAdapter} = prepareResources({library: false});
137+
138+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilderProcessor({
139+
resources: [resource],
140+
fs: fsInterface(memoryAdapter),
141+
options: {
142+
compress: false
143+
}
144+
});
145+
146+
const expected = getExpectedResults({compress: false, library: false});
147+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
148+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
149+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
150+
});
151+
152+
test("ThemeBuilder: Builds a less file", async (t) => {
153+
const {resource, memoryAdapter} = prepareResources();
154+
155+
const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});
156+
157+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource]);
158+
159+
const expected = getExpectedResults({compress: false});
160+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
161+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
162+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
163+
});
164+
165+
test("ThemeBuilder: Builds a less file (compress = true)", async (t) => {
166+
const {resource, memoryAdapter} = prepareResources();
167+
168+
const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});
169+
170+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource], {
171+
compress: true
172+
});
173+
174+
const expected = getExpectedResults({compress: true});
175+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
176+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
177+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
178+
});
179+
180+
test("ThemeBuilder: Builds a less file (compress = false)", async (t) => {
181+
const {resource, memoryAdapter} = prepareResources();
182+
183+
const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});
184+
185+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource], {
186+
compress: false
187+
});
188+
189+
const expected = getExpectedResults({compress: false});
190+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
191+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
192+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
193+
});
194+
195+
test("ThemeBuilder: Builds a less file (no library)", async (t) => {
196+
const {resource, memoryAdapter} = prepareResources({library: false});
197+
198+
const themeBuilder = new ThemeBuilder({fs: fsInterface(memoryAdapter)});
199+
200+
const [cssResource, cssRtlResource, jsonResource] = await themeBuilder.build([resource], {
201+
compress: false
202+
});
203+
204+
const expected = getExpectedResults({compress: false, library: false});
205+
t.is(await cssResource.getString(), expected.css, "CSS should be correct");
206+
t.is(await cssRtlResource.getString(), expected.cssRtl, "Right-to-left CSS should be correct");
207+
t.is(await jsonResource.getString(), expected.json, "JSON should be correct");
208+
});

0 commit comments

Comments
 (0)