less-openui5 0.11.2 → 0.11.4

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.
@@ -0,0 +1,185 @@
1
+ const path = require("path");
2
+ const createParser = require("./less/parser");
3
+ const clone = require("clone");
4
+
5
+ // Plugins
6
+ const ImportCollectorPlugin = require("./plugin/import-collector");
7
+ const VariableCollectorPlugin = require("./plugin/variable-collector");
8
+ const UrlCollector = require("./plugin/url-collector");
9
+
10
+ class Compiler {
11
+ constructor({options, fileUtils, customFs}) {
12
+ this.options = options;
13
+ this.fileUtils = fileUtils;
14
+
15
+ // Stores mapping between "virtual" paths (used within LESS) and real filesystem paths.
16
+ // Only relevant when using the "rootPaths" option.
17
+ this.mFileMappings = {};
18
+
19
+ // Only use custom file handler when "rootPaths" or custom "fs" are used
20
+ if ((this.options.rootPaths && this.options.rootPaths.length > 0) || customFs) {
21
+ this.fnFileHandler = this.createFileHandler();
22
+ } else {
23
+ this.fnFileHandler = undefined;
24
+ }
25
+ }
26
+ createFileHandler() {
27
+ return async (file, currentFileInfo, handleDataAndCallCallback, callback) => {
28
+ try {
29
+ let pathname;
30
+
31
+ // support absolute paths such as "/resources/my/base.less"
32
+ if (path.posix.isAbsolute(file)) {
33
+ pathname = path.posix.normalize(file);
34
+ } else {
35
+ pathname = path.posix.join(currentFileInfo.currentDirectory, file);
36
+ }
37
+
38
+ const result = await this.fileUtils.readFile(pathname, this.options.rootPaths);
39
+ if (!result) {
40
+ // eslint-disable-next-line no-console
41
+ console.log("File not found: " + pathname);
42
+ callback({type: "File", message: "Could not find file at path '" + pathname + "'"});
43
+ } else {
44
+ // Save import mapping to calculate full import paths later on
45
+ this.mFileMappings[currentFileInfo.rootFilename] =
46
+ this.mFileMappings[currentFileInfo.rootFilename] || {};
47
+ this.mFileMappings[currentFileInfo.rootFilename][pathname] = result.path;
48
+
49
+ handleDataAndCallCallback(pathname, result.content);
50
+ }
51
+ } catch (err) {
52
+ // eslint-disable-next-line no-console
53
+ console.log(err);
54
+ callback(err);
55
+ }
56
+ };
57
+ }
58
+ async compile(config) {
59
+ const parserOptions = clone(this.options.parser);
60
+ let rootpath;
61
+
62
+ if (config.path) {
63
+ // Keep rootpath for later usage in the ImportCollectorPlugin
64
+ rootpath = config.path;
65
+ parserOptions.filename = config.localPath;
66
+ }
67
+
68
+ // inject the library name as prefix (e.g. "sap.m" as "_sap_m")
69
+ if (this.options.library && typeof this.options.library.name === "string") {
70
+ const libName = config.libName = this.options.library.name;
71
+ config.libPath = libName.replace(/\./g, "/");
72
+ config.prefix = "_" + libName.replace(/\./g, "_") + "_";
73
+ } else {
74
+ config.prefix = ""; // no library, no prefix
75
+ }
76
+
77
+ // Keep filename for later usage (see ImportCollectorPlugin) as less modifies the parserOptions.filename
78
+ const filename = parserOptions.filename;
79
+
80
+ const parser = createParser(parserOptions, this.fnFileHandler);
81
+
82
+ function parseContent(content) {
83
+ return new Promise(function(resolve, reject) {
84
+ parser.parse(content, function(err, tree) {
85
+ if (err) {
86
+ reject(err);
87
+ } else {
88
+ resolve(tree);
89
+ }
90
+ });
91
+ });
92
+ }
93
+
94
+ const tree = await parseContent(config.content);
95
+ const result = {tree};
96
+
97
+ // plugins to collect imported files and variable values
98
+ const oImportCollector = new ImportCollectorPlugin({
99
+ importMappings: this.mFileMappings[filename]
100
+ });
101
+ const oVariableCollector = new VariableCollectorPlugin(this.options.compiler);
102
+ const oUrlCollector = new UrlCollector();
103
+
104
+ // render to css
105
+ result.css = tree.toCSS(Object.assign({}, this.options.compiler, {
106
+ plugins: [oImportCollector, oVariableCollector, oUrlCollector]
107
+ }));
108
+
109
+ // retrieve imported files
110
+ result.imports = oImportCollector.getImports();
111
+
112
+ // retrieve reduced set of variables
113
+ result.variables = oVariableCollector.getVariables(Object.keys(this.mFileMappings[filename] || {}));
114
+
115
+ // retrieve all variables
116
+ result.allVariables = oVariableCollector.getAllVariables();
117
+
118
+ // also compile rtl-version if requested
119
+ let oRTL;
120
+ if (this.options.rtl) {
121
+ const RTLPlugin = require("./plugin/rtl");
122
+ oRTL = new RTLPlugin();
123
+
124
+ const urls = oUrlCollector.getUrls();
125
+
126
+ const existingImgRtlUrls = (await Promise.all(
127
+ urls.map(async ({currentDirectory, relativeUrl}) => {
128
+ const relativeImgRtlUrl = RTLPlugin.getRtlImgUrl(relativeUrl);
129
+ if (relativeImgRtlUrl) {
130
+ const resolvedImgRtlUrl = path.posix.join(currentDirectory, relativeImgRtlUrl);
131
+ if (await this.fileUtils.findFile(resolvedImgRtlUrl, this.options.rootPaths)) {
132
+ return resolvedImgRtlUrl;
133
+ }
134
+ }
135
+ })
136
+ )).filter(Boolean);
137
+
138
+ oRTL.setExistingImgRtlPaths(existingImgRtlUrls);
139
+ }
140
+
141
+ if (oRTL) {
142
+ result.cssRtl = tree.toCSS(Object.assign({}, this.options.compiler, {
143
+ plugins: [oRTL]
144
+ }));
145
+ }
146
+
147
+ if (rootpath) {
148
+ result.imports.unshift(rootpath);
149
+ }
150
+
151
+ // also compile css-variables version if requested
152
+ if (this.options.cssVariables) {
153
+ // parse the content again to have a clean tree
154
+ const cssVariablesSkeletonTree = await parseContent(config.content);
155
+
156
+ // generate the skeleton-css and the less-variables
157
+ const CSSVariablesCollectorPlugin = require("./plugin/css-variables-collector");
158
+ const oCSSVariablesCollector = new CSSVariablesCollectorPlugin(config);
159
+ const oVariableCollector = new VariableCollectorPlugin(this.options.compiler);
160
+ result.cssSkeleton = cssVariablesSkeletonTree.toCSS(Object.assign({}, this.options.compiler, {
161
+ plugins: [oCSSVariablesCollector, oVariableCollector]
162
+ }));
163
+ const varsOverride = oVariableCollector.getAllVariables();
164
+ result.cssVariablesSource = oCSSVariablesCollector.toLessVariables(varsOverride);
165
+
166
+ if (oRTL) {
167
+ const oCSSVariablesCollectorRTL = new CSSVariablesCollectorPlugin(config);
168
+ result.cssSkeletonRtl = cssVariablesSkeletonTree.toCSS(Object.assign({}, this.options.compiler, {
169
+ plugins: [oCSSVariablesCollectorRTL, oRTL]
170
+ }));
171
+ }
172
+
173
+ // generate the css-variables content out of the less-variables
174
+ const cssVariablesTree = await parseContent(result.cssVariablesSource);
175
+ const CSSVariablesPointerPlugin = require("./plugin/css-variables-pointer");
176
+ result.cssVariables = cssVariablesTree.toCSS(Object.assign({}, this.options.compiler, {
177
+ plugins: [new CSSVariablesPointerPlugin()]
178
+ }));
179
+ }
180
+
181
+ return result;
182
+ }
183
+ }
184
+
185
+ module.exports = Compiler;
package/lib/index.js CHANGED
@@ -1,19 +1,17 @@
1
1
  "use strict";
2
2
 
3
3
  const path = require("path");
4
- const clone = require("clone");
5
- const css = require("css");
4
+ const css = require("@adobe/css-tools");
5
+
6
6
 
7
- const createParser = require("./less/parser");
8
7
  const diff = require("./diff");
9
8
  const scope = require("./scope");
10
9
 
11
10
  const fileUtilsFactory = require("./fileUtils");
12
11
 
13
- // Plugins
14
- const ImportCollectorPlugin = require("./plugin/import-collector");
15
- const VariableCollectorPlugin = require("./plugin/variable-collector");
16
- const UrlCollector = require("./plugin/url-collector");
12
+ const Compiler = require("./Compiler");
13
+
14
+ const themingParametersDataUri = require("./themingParameters/dataUri");
17
15
 
18
16
  // Workaround for a performance issue in the "css" parser module when used in combination
19
17
  // with the "colors" module that enhances the String prototype.
@@ -104,7 +102,7 @@ Builder.prototype.cacheTheme = function(result) {
104
102
  };
105
103
 
106
104
  /**
107
- * Creates a themebuild
105
+ * Runs a theme build
108
106
  * @param {object} options
109
107
  * @param {object} options.compiler compiler object as passed to less
110
108
  * @param {boolean} options.cssVariables whether or not to enable css variables output
@@ -115,10 +113,6 @@ Builder.prototype.cacheTheme = function(result) {
115
113
  Builder.prototype.build = function(options) {
116
114
  const that = this;
117
115
 
118
- // Stores mapping between "virtual" paths (used within LESS) and real filesystem paths.
119
- // Only relevant when using the "rootPaths" option.
120
- const mFileMappings = {};
121
-
122
116
  // Assign default options
123
117
  options = Object.assign({
124
118
  lessInput: null,
@@ -143,216 +137,14 @@ Builder.prototype.build = function(options) {
143
137
  options.parser.relativeUrls = true;
144
138
  }
145
139
 
146
- function fileHandler(file, currentFileInfo, handleDataAndCallCallback, callback) {
147
- let pathname;
148
-
149
- // support absolute paths such as "/resources/my/base.less"
150
- if (path.posix.isAbsolute(file)) {
151
- pathname = path.posix.normalize(file);
152
- } else {
153
- pathname = path.posix.join(currentFileInfo.currentDirectory, file);
154
- }
155
-
156
- that.fileUtils.readFile(pathname, options.rootPaths).then(function(result) {
157
- if (!result) {
158
- // eslint-disable-next-line no-console
159
- console.log("File not found: " + pathname);
160
- callback({type: "File", message: "Could not find file at path '" + pathname + "'"});
161
- } else {
162
- try {
163
- // Save import mapping to calculate full import paths later on
164
- mFileMappings[currentFileInfo.rootFilename] = mFileMappings[currentFileInfo.rootFilename] || {};
165
- mFileMappings[currentFileInfo.rootFilename][pathname] = result.path;
166
-
167
- handleDataAndCallCallback(pathname, result.content);
168
- } catch (e) {
169
- // eslint-disable-next-line no-console
170
- console.log(e);
171
- callback(e);
172
- }
173
- }
174
- }, function(err) {
175
- // eslint-disable-next-line no-console
176
- console.log(err);
177
- callback(err);
178
- });
179
- }
180
-
181
- function compile(config) {
182
- const parserOptions = clone(options.parser);
183
- let rootpath;
184
-
185
- if (config.path) {
186
- // Keep rootpath for later usage in the ImportCollectorPlugin
187
- rootpath = config.path;
188
- parserOptions.filename = config.localPath;
189
- }
190
-
191
- // inject the library name as prefix (e.g. "sap.m" as "_sap_m")
192
- if (options.library && typeof options.library.name === "string") {
193
- const libName = config.libName = options.library.name;
194
- config.libPath = libName.replace(/\./g, "/");
195
- config.prefix = "_" + libName.replace(/\./g, "_") + "_";
196
- } else {
197
- config.prefix = ""; // no library, no prefix
198
- }
199
-
200
- // Keep filename for later usage (see ImportCollectorPlugin) as less modifies the parserOptions.filename
201
- const filename = parserOptions.filename;
202
-
203
- // Only use custom file handler when "rootPaths" or custom "fs" are used
204
- let fnFileHandler;
205
- if ((options.rootPaths && options.rootPaths.length > 0) || that.customFs) {
206
- fnFileHandler = fileHandler;
207
- }
208
-
209
- const parser = createParser(parserOptions, fnFileHandler);
210
-
211
- return new Promise(function(resolve, reject) {
212
- parser.parse(config.content, function(err, tree) {
213
- if (err) {
214
- reject(err);
215
- } else {
216
- resolve(tree);
217
- }
218
- });
219
- }).then(async function(tree) {
220
- const result = {};
221
-
222
- result.tree = tree;
223
-
224
- // plugins to collect imported files and variable values
225
- const oImportCollector = new ImportCollectorPlugin({
226
- importMappings: mFileMappings[filename]
227
- });
228
- const oVariableCollector = new VariableCollectorPlugin(options.compiler);
229
- const oUrlCollector = new UrlCollector();
230
-
231
- // render to css
232
- result.css = tree.toCSS(Object.assign({}, options.compiler, {
233
- plugins: [oImportCollector, oVariableCollector, oUrlCollector]
234
- }));
235
-
236
- // retrieve imported files
237
- result.imports = oImportCollector.getImports();
238
-
239
- // retrieve reduced set of variables
240
- result.variables = oVariableCollector.getVariables(Object.keys(mFileMappings[filename] || {}));
241
-
242
- // retrieve all variables
243
- result.allVariables = oVariableCollector.getAllVariables();
244
-
245
- // also compile rtl-version if requested
246
- let oRTL;
247
- if (options.rtl) {
248
- const RTLPlugin = require("./plugin/rtl");
249
- oRTL = new RTLPlugin();
250
-
251
- const urls = oUrlCollector.getUrls();
252
-
253
- const existingImgRtlUrls = (await Promise.all(
254
- urls.map(async ({currentDirectory, relativeUrl}) => {
255
- const relativeImgRtlUrl = RTLPlugin.getRtlImgUrl(relativeUrl);
256
- if (relativeImgRtlUrl) {
257
- const resolvedImgRtlUrl = path.posix.join(currentDirectory, relativeImgRtlUrl);
258
- if (await that.fileUtils.findFile(resolvedImgRtlUrl, options.rootPaths)) {
259
- return resolvedImgRtlUrl;
260
- }
261
- }
262
- })
263
- )).filter(Boolean);
264
-
265
- oRTL.setExistingImgRtlPaths(existingImgRtlUrls);
266
- }
267
-
268
- if (oRTL) {
269
- result.cssRtl = tree.toCSS(Object.assign({}, options.compiler, {
270
- plugins: [oRTL]
271
- }));
272
- }
273
-
274
- if (rootpath) {
275
- result.imports.unshift(rootpath);
276
- }
277
-
278
- // also compile css-variables version if requested
279
- if (options.cssVariables) {
280
- return new Promise(function(resolve, reject) {
281
- // parse the content again to have a clean tree
282
- parser.parse(config.content, function(err, tree) {
283
- if (err) {
284
- reject(err);
285
- } else {
286
- resolve(tree);
287
- }
288
- });
289
- }).then(function(tree) {
290
- // generate the skeleton-css and the less-variables
291
- const CSSVariablesCollectorPlugin = require("./plugin/css-variables-collector");
292
- const oCSSVariablesCollector = new CSSVariablesCollectorPlugin(config);
293
- const oVariableCollector = new VariableCollectorPlugin(options.compiler);
294
- result.cssSkeleton = tree.toCSS(Object.assign({}, options.compiler, {
295
- plugins: [oCSSVariablesCollector, oVariableCollector]
296
- }));
297
- const varsOverride = oVariableCollector.getAllVariables();
298
- result.cssVariablesSource = oCSSVariablesCollector.toLessVariables(varsOverride);
299
- if (oRTL) {
300
- const oCSSVariablesCollectorRTL = new CSSVariablesCollectorPlugin(config);
301
- result.cssSkeletonRtl = tree.toCSS(Object.assign({}, options.compiler, {
302
- plugins: [oCSSVariablesCollectorRTL, oRTL]
303
- }));
304
- }
305
- return tree;
306
- }).then(function(tree) {
307
- // generate the css-variables content out of the less-variables
308
- return new Promise(function(resolve, reject) {
309
- parser.parse(result.cssVariablesSource, function(err, tree) {
310
- if (err) {
311
- reject(err);
312
- } else {
313
- const CSSVariablesPointerPlugin = require("./plugin/css-variables-pointer");
314
- result.cssVariables = tree.toCSS(Object.assign({}, options.compiler, {
315
- plugins: [new CSSVariablesPointerPlugin()]
316
- }));
317
- resolve(result);
318
- }
319
- });
320
- });
321
- });
322
- }
323
-
324
- return result;
325
- });
326
- }
140
+ const compiler = new Compiler({
141
+ options,
142
+ fileUtils: this.fileUtils,
143
+ customFs: this.customFs
144
+ });
327
145
 
328
146
  function addInlineParameters(result) {
329
- return new Promise(function(resolve, reject) {
330
- if (typeof options.library === "object" && typeof options.library.name === "string") {
331
- const parameters = JSON.stringify(result.variables);
332
-
333
- // properly escape the parameters to be part of a data-uri
334
- // + escaping single quote (') as it is used to surround the data-uri: url('...')
335
- const escapedParameters = encodeURIComponent(parameters).replace(/'/g, function(char) {
336
- return escape(char);
337
- });
338
-
339
- // embed parameter variables as plain-text string into css
340
- const parameterStyleRule = "\n/* Inline theming parameters */\n#sap-ui-theme-" +
341
- options.library.name.replace(/\./g, "\\.") +
342
- "{background-image:url('data:text/plain;utf-8," + escapedParameters + "')}\n";
343
-
344
- // embed parameter variables as plain-text string into css
345
- result.css += parameterStyleRule;
346
- if (options.rtl) {
347
- result.cssRtl += parameterStyleRule;
348
- }
349
- if (options.cssVariables) {
350
- // for the css variables build we just add it to the variables
351
- result.cssVariables += parameterStyleRule;
352
- }
353
- }
354
- resolve(result);
355
- });
147
+ return themingParametersDataUri.addInlineParameters({result, options});
356
148
  }
357
149
 
358
150
  function getScopeVariables(options) {
@@ -385,13 +177,13 @@ Builder.prototype.build = function(options) {
385
177
  if (!config) {
386
178
  throw new Error("Could not find embeddedCompareFile at path '" + scopeOptions.embeddedCompareFilePath + "'");
387
179
  }
388
- return compile(config);
180
+ return compiler.compile(config);
389
181
  }),
390
182
  that.fileUtils.readFile(scopeOptions.embeddedFilePath, options.rootPaths).then(function(config) {
391
183
  if (!config) {
392
184
  throw new Error("Could not find embeddedFile at path '" + scopeOptions.embeddedFilePath + "'");
393
185
  }
394
- return compile(config);
186
+ return compiler.compile(config);
395
187
  })
396
188
  ]).then(function(results) {
397
189
  return {
@@ -533,7 +325,9 @@ Builder.prototype.build = function(options) {
533
325
  }
534
326
 
535
327
  // No css diffing and scoping
536
- return that.fileUtils.readFile(options.lessInputPath, options.rootPaths).then(compile);
328
+ return that.fileUtils.readFile(options.lessInputPath, options.rootPaths).then((config) => {
329
+ return compiler.compile(config);
330
+ });
537
331
  });
538
332
  }
539
333
 
@@ -546,7 +340,7 @@ Builder.prototype.build = function(options) {
546
340
  }
547
341
 
548
342
  if (options.lessInput) {
549
- return compile({
343
+ return compiler.compile({
550
344
  content: options.lessInput
551
345
  }).then(addInlineParameters).then(that.cacheTheme.bind(that));
552
346
  } else {
@@ -11,6 +11,7 @@ const CSSVariablesCollectorPlugin = module.exports = function(config) {
11
11
  this.ruleStack = [];
12
12
  this.mixinStack = [];
13
13
  this.parenStack = [];
14
+ this.fontFaceDirectiveStack = [];
14
15
  };
15
16
 
16
17
  CSSVariablesCollectorPlugin.prototype = {
@@ -20,8 +21,8 @@ CSSVariablesCollectorPlugin.prototype = {
20
21
 
21
22
  isReplacing: true,
22
23
 
23
- _isInMixinOrParen() {
24
- return this.mixinStack.length > 0 || this.parenStack.length > 0;
24
+ _isInMixinOrParenOrFontFaceDirective() {
25
+ return this.mixinStack.length > 0 || this.parenStack.length > 0 || this.fontFaceDirectiveStack.length > 0;
25
26
  },
26
27
 
27
28
  _isVarInRule() {
@@ -39,39 +40,36 @@ CSSVariablesCollectorPlugin.prototype = {
39
40
  },
40
41
 
41
42
  _isRelevant() {
42
- return !this._isInMixinOrParen() && this._isVarInRule();
43
+ return !this._isInMixinOrParenOrFontFaceDirective() && this._isVarInRule();
43
44
  },
44
45
 
45
46
  toLessVariables(varsOverride) {
46
47
  const vars = {};
47
- Object.keys(this.vars).forEach((key) => {
48
- const override = this.vars[key].updateAfterEval && varsOverride[key] !== undefined;
49
- /*
50
- if (override) {
51
- console.log(`Override variable "${key}" from "${this.vars[key].css}" to "${varsOverride[key]}"`);
52
- }
53
- */
54
- vars[key] = {
55
- css: override ? varsOverride[key] : this.vars[key].css,
56
- export: this.vars[key].export
48
+ Object.keys(this.vars).forEach((variableName) => {
49
+ const override = this.vars[variableName].updateAfterEval && varsOverride[variableName] !== undefined;
50
+ vars[variableName] = {
51
+ css: override ? varsOverride[variableName] : this.vars[variableName].css,
52
+ export: this.vars[variableName].export
57
53
  };
58
54
  });
59
55
  let lessVariables = "";
60
- Object.keys(vars).forEach((value, index) => {
61
- lessVariables += "@" + value + ": " + vars[value].css + ";\n";
56
+ Object.keys(vars).forEach((variableName) => {
57
+ const variableValue = vars[variableName].css;
58
+ lessVariables += `@${variableName}: ${variableValue};\n`;
62
59
  });
63
- Object.keys(this.calcVars).forEach((value, index) => {
64
- lessVariables += "@" + value + ": " + this.calcVars[value].css + ";\n";
60
+ Object.keys(this.calcVars).forEach((variableName) => {
61
+ const variableValue = this.calcVars[variableName].css;
62
+ lessVariables += `@${variableName}: ${variableValue};\n`;
65
63
  });
66
64
  lessVariables += "\n:root {\n";
67
- Object.keys(vars).forEach((value, index) => {
68
- if (vars[value].export) {
69
- lessVariables += "--" + value + ": @" + value + ";\n";
65
+ Object.keys(vars).forEach((variableName) => {
66
+ if (vars[variableName].export) {
67
+ lessVariables += `--${variableName}: @${variableName};\n`;
70
68
  }
71
69
  });
72
- Object.keys(this.calcVars).forEach((value, index) => {
73
- if (this.calcVars[value].export) {
74
- lessVariables += "--" + value + ": @" + value + ";\n";
70
+ Object.keys(this.calcVars).forEach((variableName) => {
71
+ if (this.calcVars[variableName].export) {
72
+ lessVariables += `--${variableName}: @${variableName};\n`;
75
73
  }
76
74
  });
77
75
  lessVariables += "}\n";
@@ -156,7 +154,7 @@ CSSVariablesCollectorPlugin.prototype = {
156
154
  visitRule(node, visitArgs) {
157
155
  // check rule for being a variable declaration
158
156
  const isVarDeclaration = typeof node.name === "string" && node.name.startsWith("@");
159
- if (!this._isInMixinOrParen() && isVarDeclaration) {
157
+ if (!this._isInMixinOrParenOrFontFaceDirective() && isVarDeclaration) {
160
158
  // add the variable declaration to the list of vars
161
159
  const varName = node.name.substr(1);
162
160
  const isVarInLib = this._isVarInLibrary({
@@ -202,6 +200,22 @@ CSSVariablesCollectorPlugin.prototype = {
202
200
  return node;
203
201
  },
204
202
 
203
+ visitDirective(node, visitArgs) {
204
+ // store the @font-face directive context
205
+ if (node.name === "@font-face") {
206
+ this.fontFaceDirectiveStack.push(node);
207
+ }
208
+ return node;
209
+ },
210
+
211
+ visitDirectiveOut(node) {
212
+ // remove @font-face directive context
213
+ if (node.name === "@font-face") {
214
+ this.fontFaceDirectiveStack.pop();
215
+ }
216
+ return node;
217
+ },
218
+
205
219
  visitUrl(node, visitArgs) {
206
220
  // we mark the less variables which should be updated after eval
207
221
  // => strangewise less variables with "none" values are also urls
@@ -0,0 +1,33 @@
1
+ module.exports = {
2
+ addInlineParameters: function({result, options}) {
3
+ // Inline parameters can only be added when the library name is known
4
+ if (typeof options.library !== "object" || typeof options.library.name !== "string") {
5
+ return result;
6
+ }
7
+
8
+ const parameters = JSON.stringify(result.variables);
9
+
10
+ // properly escape the parameters to be part of a data-uri
11
+ // + escaping single quote (') as it is used to surround the data-uri: url('...')
12
+ const escapedParameters = encodeURIComponent(parameters).replace(/'/g, function(char) {
13
+ return escape(char);
14
+ });
15
+
16
+ // embed parameter variables as plain-text string into css
17
+ const parameterStyleRule = "\n/* Inline theming parameters */\n#sap-ui-theme-" +
18
+ options.library.name.replace(/\./g, "\\.") +
19
+ "{background-image:url('data:text/plain;utf-8," + escapedParameters + "')}\n";
20
+
21
+ // embed parameter variables as plain-text string into css
22
+ result.css += parameterStyleRule;
23
+ if (options.rtl) {
24
+ result.cssRtl += parameterStyleRule;
25
+ }
26
+ if (options.cssVariables) {
27
+ // for the css variables build we just add it to the variables
28
+ result.cssVariables += parameterStyleRule;
29
+ }
30
+
31
+ return result;
32
+ }
33
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "less-openui5",
3
- "version": "0.11.2",
3
+ "version": "0.11.4",
4
4
  "description": "Build OpenUI5 themes with Less.js",
5
5
  "author": {
6
6
  "name": "SAP SE",
@@ -23,8 +23,8 @@
23
23
  },
24
24
  "scripts": {
25
25
  "lint": "eslint ./",
26
- "unit": "mocha test/*.js",
27
- "unit-debug": "mocha --inspect --inspect-brk test/*.js",
26
+ "unit": "mocha test/*.js test/lib/**",
27
+ "unit-debug": "mocha --inspect --inspect-brk test/*.js test/lib/**",
28
28
  "coverage": "nyc npm run unit",
29
29
  "test": "npm run lint && npm run coverage && npm run depcheck",
30
30
  "preversion": "npm test",
@@ -52,10 +52,10 @@
52
52
  "lib/thirdparty/**"
53
53
  ],
54
54
  "check-coverage": true,
55
- "statements": 90,
55
+ "statements": 95,
56
56
  "branches": 85,
57
- "functions": 90,
58
- "lines": 90,
57
+ "functions": 100,
58
+ "lines": 95,
59
59
  "watermarks": {
60
60
  "statements": [
61
61
  70,
@@ -82,17 +82,17 @@
82
82
  "url": "git@github.com:SAP/less-openui5.git"
83
83
  },
84
84
  "dependencies": {
85
- "clone": "^2.1.0",
86
- "css": "^3.0.0",
85
+ "@adobe/css-tools": "^4.0.1",
86
+ "clone": "^2.1.2",
87
87
  "mime": "^1.6.0"
88
88
  },
89
89
  "devDependencies": {
90
- "depcheck": "^1.4.2",
91
- "eslint": "^7.29.0",
90
+ "depcheck": "^1.4.3",
91
+ "eslint": "^7.32.0",
92
92
  "eslint-config-google": "^0.14.0",
93
- "graceful-fs": "^4.2.6",
93
+ "graceful-fs": "^4.2.10",
94
94
  "mocha": "^8.4.0",
95
95
  "nyc": "^15.1.0",
96
- "sinon": "^10.0.0"
96
+ "sinon": "^11.1.2"
97
97
  }
98
98
  }
package/CHANGELOG.md DELETED
@@ -1,240 +0,0 @@
1
- # Changelog
2
- All notable changes to this project will be documented in this file.
3
- This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
4
-
5
- A list of unreleased changes can be found [here](https://github.com/SAP/less-openui5/compare/v0.11.2...HEAD).
6
-
7
- <a name="v0.11.2"></a>
8
- ## [v0.11.2] - 2021-06-28
9
- ### Bug Fixes
10
- - **CSS Variables:** Fix variable handling / relative urls ([#172](https://github.com/SAP/less-openui5/issues/172)) [`6ace17f`](https://github.com/SAP/less-openui5/commit/6ace17fda10d47d0e33be91100bd3089c293a483)
11
-
12
-
13
- <a name="v0.11.1"></a>
14
- ## [v0.11.1] - 2021-03-17
15
- ### Bug Fixes
16
- - **Variables:** Include variables defined in sub-directories ([#160](https://github.com/SAP/less-openui5/issues/160)) [`5568cd6`](https://github.com/SAP/less-openui5/commit/5568cd6e10bbf440a35b4bd0d8b7926cb1bbb149)
17
-
18
-
19
- <a name="v0.11.0"></a>
20
- ## [v0.11.0] - 2021-03-10
21
- ### Breaking Changes
22
- - Only rewrite image paths for RTL-variant when files exist ([#162](https://github.com/SAP/less-openui5/issues/162)) [`88e7a74`](https://github.com/SAP/less-openui5/commit/88e7a7436fc7f197186c780a856bb9c6dff7c582)
23
-
24
- ### BREAKING CHANGE
25
-
26
- This affects the output of the `rtl` (right-to-left) variant that is created by applying several mechanisms to create a mirrored variant of the CSS to be used in locales that use a right to left text direction.
27
-
28
- One aspect is adopting urls which contain an `img` folder in the path.
29
- Before this change, all urls have been changed to use a `img-RTL` folder instead. This allows mirrored images to be used, but it also requires an images to be available on that path even when the original image should be used (e.g. for a logo).
30
-
31
- With this change:
32
- - Urls are only adopted in case an `img-RTL` variant of that file exists
33
- - Urls with a protocol (http/https/data/...) or starting with a slash (`/`) are not adopted anymore
34
-
35
-
36
- <a name="v0.10.0"></a>
37
- ## [v0.10.0] - 2021-01-29
38
- ### Breaking Changes
39
- - **Security:** Disable JavaScript execution in Less.js [`c0d3a85`](https://github.com/SAP/less-openui5/commit/c0d3a8572974a20ea6cee42da11c614a54f100e8)
40
-
41
- ### BREAKING CHANGE
42
-
43
- Parser option `javascriptEnabled` has been removed. JavaScript is always
44
- disabled and cannot be enabled.
45
-
46
-
47
- <a name="v0.9.0"></a>
48
- ## [v0.9.0] - 2020-11-06
49
- ### Breaking Changes
50
- - Remove support for import over http(s) [`e4a1c86`](https://github.com/SAP/less-openui5/commit/e4a1c86b994430fa3e640dc7b09a6c09a1b2845b)
51
- - Require Node.js >= 10 [`47f244e`](https://github.com/SAP/less-openui5/commit/47f244ec37ab5ff51c88cd2dd96c4110f2779694)
52
-
53
- ### BREAKING CHANGE
54
-
55
- Import over http(s) is not supported anymore.
56
- Use the Builder 'fs' option to provide an interface that also handles
57
- http(s) resources.
58
-
59
- Support for older Node.js releases has been dropped.
60
- Only Node.js v10 or higher is supported.
61
-
62
-
63
- <a name="v0.8.7"></a>
64
- ## [v0.8.7] - 2020-06-26
65
- ### Bug Fixes
66
- - Error handling for missing scoping files [`c7513a1`](https://github.com/SAP/less-openui5/commit/c7513a101a2f01e9114ff86f5be598a29bc51be0)
67
-
68
-
69
- <a name="v0.8.6"></a>
70
- ## [v0.8.6] - 2020-02-24
71
- ### Bug Fixes
72
- - CSS var assignment only for less to less vars ([#116](https://github.com/SAP/less-openui5/issues/116)) [`2e9560d`](https://github.com/SAP/less-openui5/commit/2e9560dd2b89f7b1f3e09fcc3d0bfe867496a3fc)
73
-
74
-
75
- <a name="v0.8.5"></a>
76
- ## [v0.8.5] - 2020-02-21
77
- ### Features
78
- - Keep linking of less vars for css vars ([#115](https://github.com/SAP/less-openui5/issues/115)) [`3f99e9d`](https://github.com/SAP/less-openui5/commit/3f99e9d49fac620405dcad48556f5c4dfcf916c4)
79
-
80
-
81
- <a name="v0.8.4"></a>
82
- ## [v0.8.4] - 2020-02-10
83
- ### Features
84
- - Add experimental CSS variables and skeleton build ([#108](https://github.com/SAP/less-openui5/issues/108)) [`e6d8503`](https://github.com/SAP/less-openui5/commit/e6d85038f077ff252e8240d9924e7c4761ac4e5e)
85
-
86
-
87
- <a name="v0.8.3"></a>
88
- ## [v0.8.3] - 2020-01-07
89
- ### Bug Fixes
90
- - Diff algorithm exception ([#110](https://github.com/SAP/less-openui5/issues/110)) [`9628a6c`](https://github.com/SAP/less-openui5/commit/9628a6c6386b671e37a3c9680ca3b5fbd6175146)
91
-
92
-
93
- <a name="v0.8.2"></a>
94
- ## [v0.8.2] - 2019-12-16
95
- ### Bug Fixes
96
- - Support absolute import paths in less files ([#107](https://github.com/SAP/less-openui5/issues/107)) [`266b06d`](https://github.com/SAP/less-openui5/commit/266b06d9b091d34e6f279fbdf567702bcb9dbaed)
97
-
98
-
99
- <a name="v0.8.1"></a>
100
- ## [v0.8.1] - 2019-12-03
101
- ### Bug Fixes
102
- - Improve rule diffing algorithm ([#104](https://github.com/SAP/less-openui5/issues/104)) [`2527189`](https://github.com/SAP/less-openui5/commit/252718912861d2edde2041729a106fb3e0a6316b)
103
-
104
-
105
- <a name="v0.8.0"></a>
106
- ## [v0.8.0] - 2019-11-18
107
- ### Breaking Changes
108
- - Remove support for 'sourceMap' / 'cleancss' options [`3f234c8`](https://github.com/SAP/less-openui5/commit/3f234c88c4442035c0fe2683197c044ec6a93fab)
109
-
110
- ### Bug Fixes
111
- - Apply less.js fix for import race condition [`694f6c4`](https://github.com/SAP/less-openui5/commit/694f6c41ad788eded034df6835cf5fbd8f6feaf3)
112
-
113
-
114
- <a name="0.7.0"></a>
115
- ## [0.7.0] - 2019-10-30
116
- ### Breaking Changes
117
- - Drop support for Node.js < 8.5 [`810962c`](https://github.com/SAP/less-openui5/commit/810962cf7bb4604641160d547593568f70b72f98)
118
-
119
- ### Bug Fixes
120
- - Add inline parameters on empty CSS [`bc59d58`](https://github.com/SAP/less-openui5/commit/bc59d58486e972057675c5b8abe83229f116bc07)
121
- - Scope rule handling ([#92](https://github.com/SAP/less-openui5/issues/92)) [`89b56c1`](https://github.com/SAP/less-openui5/commit/89b56c1a975f53ea8e436878b07707f1fb061486)
122
-
123
-
124
- [v0.11.2]: https://github.com/SAP/less-openui5/compare/v0.11.1...v0.11.2
125
- [v0.11.1]: https://github.com/SAP/less-openui5/compare/v0.11.0...v0.11.1
126
- [v0.11.0]: https://github.com/SAP/less-openui5/compare/v0.10.0...v0.11.0
127
- [v0.10.0]: https://github.com/SAP/less-openui5/compare/v0.9.0...v0.10.0
128
- [v0.9.0]: https://github.com/SAP/less-openui5/compare/v0.8.7...v0.9.0
129
- [v0.8.7]: https://github.com/SAP/less-openui5/compare/v0.8.6...v0.8.7
130
- [v0.8.6]: https://github.com/SAP/less-openui5/compare/v0.8.5...v0.8.6
131
- [v0.8.5]: https://github.com/SAP/less-openui5/compare/v0.8.4...v0.8.5
132
- [v0.8.4]: https://github.com/SAP/less-openui5/compare/v0.8.3...v0.8.4
133
- [v0.8.3]: https://github.com/SAP/less-openui5/compare/v0.8.2...v0.8.3
134
- [v0.8.2]: https://github.com/SAP/less-openui5/compare/v0.8.1...v0.8.2
135
- [v0.8.1]: https://github.com/SAP/less-openui5/compare/v0.8.0...v0.8.1
136
- [v0.8.0]: https://github.com/SAP/less-openui5/compare/0.7.0...v0.8.0
137
- [0.7.0]: https://github.com/SAP/less-openui5/compare/0.6.0...0.7.0
138
- ## 0.6.0 - 2018-09-10
139
-
140
- ### Breaking changes
141
- - Drop unsupported Node.js versions. Now requires >= 6 [#45](https://github.com/SAP/less-openui5/pull/45)
142
-
143
- ### Fixes
144
- - Again, fix inline theme parameters encoding for '#' [#48](https://github.com/SAP/less-openui5/pull/48)
145
-
146
- ### All changes
147
- [`0.5.4...0.6.0`](https://github.com/SAP/less-openui5/compare/0.5.4...0.6.0)
148
-
149
-
150
- ## 0.5.4 - 2018-07-04
151
-
152
- ### Fixes
153
- - Revert "Fix inline theme parameters encoding for '#'" [#26](https://github.com/SAP/less-openui5/pull/26)
154
-
155
- ### All changes
156
- [`0.5.3...0.5.4`](https://github.com/SAP/less-openui5/compare/0.5.3...0.5.4)
157
-
158
-
159
- ## 0.5.3 - 2018-05-18
160
-
161
- ### Fixes
162
- - Fix less error propagation [#22](https://github.com/SAP/less-openui5/pull/22)
163
- - Fix inline theme parameters encoding for '#' [#23](https://github.com/SAP/less-openui5/pull/23)
164
-
165
- ### All changes
166
- [`0.5.2...0.5.3`](https://github.com/SAP/less-openui5/compare/0.5.2...0.5.3)
167
-
168
-
169
- ## 0.5.2 - 2018-03-26
170
-
171
- ### Fixes
172
- - Fix reduced set of variables [#20](https://github.com/SAP/less-openui5/pull/20)
173
-
174
- ### All changes
175
- [`0.5.1...0.5.2`](https://github.com/SAP/less-openui5/compare/0.5.1...0.5.2)
176
-
177
-
178
- ## 0.5.1 - 2018-03-12
179
-
180
- ### Fixes
181
- - Changed paths in variable collector to posix variant [#19](https://github.com/SAP/less-openui5/pull/19)
182
-
183
- ### All changes
184
- [`0.5.0...0.5.1`](https://github.com/SAP/less-openui5/compare/0.5.0...0.5.1)
185
-
186
-
187
- ## 0.5.0 - 2018-02-09
188
-
189
- ### Features
190
- - Reduce collected variables to only add relevant ones [#18](https://github.com/SAP/less-openui5/pull/18)
191
-
192
- ### All changes
193
- [`0.4.0...0.5.0`](https://github.com/SAP/less-openui5/compare/0.4.0...0.5.0)
194
-
195
-
196
- ## 0.4.0 - 2017-12-13
197
-
198
- ### Features
199
- - Add scope option [#16](https://github.com/SAP/less-openui5/pull/16)
200
- - Add custom fs option [#17](https://github.com/SAP/less-openui5/pull/17)
201
-
202
- ### All changes
203
- [`0.3.1...0.4.0`](https://github.com/SAP/less-openui5/compare/0.3.1...0.4.0)
204
-
205
-
206
- ## 0.3.1 - 2017-03-28
207
-
208
- ### Fixes
209
- - Performance workaround: Handle properties directly added to String proto [#12](https://github.com/SAP/less-openui5/pull/12)
210
-
211
- ### All changes
212
- [`0.3.0...0.3.1`](https://github.com/SAP/less-openui5/compare/0.3.0...0.3.1)
213
-
214
-
215
- ## 0.3.0 - 2017-03-23
216
-
217
- ### Breaking changes
218
- - Drop support for Node.js v0.10 [#5](https://github.com/SAP/less-openui5/pull/5)
219
- - Replace static `build` function with `Builder` class to enable caching of build results [#10](https://github.com/SAP/less-openui5/pull/10)
220
- - Refactor options to also include input LESS string [#6](https://github.com/SAP/less-openui5/pull/6)
221
-
222
- ### Features
223
- - Added "lessInputPath" option to provide a path relative to the "rootPaths" [#10](https://github.com/SAP/less-openui5/pull/10)
224
- - Added diffing and scoping to support Belize contrast areas [#10](https://github.com/SAP/less-openui5/pull/10)
225
- - Analyze .theming files as theme scope indicators [#10](https://github.com/SAP/less-openui5/pull/10)
226
-
227
- ### All changes
228
- [`0.2.0...0.3.0`](https://github.com/SAP/less-openui5/compare/0.2.0...0.3.0)
229
-
230
-
231
- ## 0.2.0 - 2016-03-15
232
-
233
- ### Breaking changes
234
- - Set default of parser option `relativeUrls` to `true` [`00d892b`](https://github.com/SAP/less-openui5/commit/00d892b95c8c0401b8a61f1b1709dfc4a68cfa26)
235
-
236
- ### Features
237
- - Include inline theming parameters [`4fa91b9`](https://github.com/SAP/less-openui5/commit/4fa91b997251f44ae3796e9f8396b45327005b13)
238
-
239
- ### All changes
240
- [`0.1.3...0.2.0`](https://github.com/SAP/less-openui5/compare/0.1.3...0.2.0)