less 3.10.0-beta.2 → 3.10.3
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/.DS_Store +0 -0
- package/bin/lessc +6652 -5505
- package/dist/less.cjs.js +6593 -5448
- package/dist/less.js +10 -6
- package/dist/less.min.js +2 -2
- package/dist/less.min.js.map +1 -1
- package/lib/less/constants.js +13 -0
- package/lib/less/contexts.js +164 -0
- package/lib/less/data/colors.js +150 -0
- package/lib/less/data/index.js +4 -0
- package/lib/less/data/unit-conversions.js +21 -0
- package/lib/less/default-options.js +68 -0
- package/lib/less/environment/abstract-file-manager.js +127 -0
- package/lib/less/environment/abstract-plugin-loader.js +187 -0
- package/lib/less/environment/environment-api.js +25 -0
- package/lib/less/environment/environment.js +59 -0
- package/lib/less/environment/file-manager-api.js +103 -0
- package/lib/less/functions/boolean.js +13 -0
- package/lib/less/functions/color-blending.js +84 -0
- package/lib/less/functions/color.js +417 -0
- package/lib/less/functions/data-uri.js +74 -0
- package/lib/less/functions/default.js +25 -0
- package/lib/less/functions/function-caller.js +49 -0
- package/lib/less/functions/function-registry.js +35 -0
- package/lib/less/functions/index.js +33 -0
- package/lib/less/functions/list.js +143 -0
- package/lib/less/functions/math-helper.js +15 -0
- package/lib/less/functions/math.js +28 -0
- package/lib/less/functions/number.js +89 -0
- package/lib/less/functions/string.js +36 -0
- package/lib/less/functions/svg.js +87 -0
- package/lib/less/functions/types.js +70 -0
- package/lib/less/import-manager.js +169 -0
- package/lib/less/index.js +92 -0
- package/lib/less/less-error.js +140 -0
- package/lib/less/logger.js +34 -0
- package/lib/less/parse-tree.js +66 -0
- package/lib/less/parse.js +89 -0
- package/lib/less/parser/chunker.js +122 -0
- package/lib/less/parser/parser-input.js +390 -0
- package/lib/less/parser/parser.js +2418 -0
- package/lib/less/plugin-manager.js +168 -0
- package/lib/less/render.js +42 -0
- package/lib/less/source-map-builder.js +77 -0
- package/lib/less/source-map-output.js +149 -0
- package/lib/less/transform-tree.js +96 -0
- package/lib/less/tree/anonymous.js +37 -0
- package/lib/less/tree/assignment.js +33 -0
- package/lib/less/tree/atrule.js +165 -0
- package/lib/less/tree/attribute.js +34 -0
- package/lib/less/tree/call.js +105 -0
- package/lib/less/tree/color.js +246 -0
- package/lib/less/tree/combinator.js +29 -0
- package/lib/less/tree/comment.js +29 -0
- package/lib/less/tree/condition.js +43 -0
- package/lib/less/tree/debug-info.js +34 -0
- package/lib/less/tree/declaration.js +115 -0
- package/lib/less/tree/detached-ruleset.js +30 -0
- package/lib/less/tree/dimension.js +179 -0
- package/lib/less/tree/element.js +73 -0
- package/lib/less/tree/expression.js +74 -0
- package/lib/less/tree/extend.js +66 -0
- package/lib/less/tree/import.js +184 -0
- package/lib/less/tree/index.js +54 -0
- package/lib/less/tree/javascript.js +33 -0
- package/lib/less/tree/js-eval-node.js +58 -0
- package/lib/less/tree/keyword.js +21 -0
- package/lib/less/tree/media.js +154 -0
- package/lib/less/tree/mixin-call.js +215 -0
- package/lib/less/tree/mixin-definition.js +229 -0
- package/lib/less/tree/namespace-value.js +87 -0
- package/lib/less/tree/negative.js +26 -0
- package/lib/less/tree/node.js +178 -0
- package/lib/less/tree/operation.js +62 -0
- package/lib/less/tree/paren.js +22 -0
- package/lib/less/tree/property.js +77 -0
- package/lib/less/tree/quoted.js +70 -0
- package/lib/less/tree/ruleset.js +867 -0
- package/lib/less/tree/selector.js +146 -0
- package/lib/less/tree/unicode-descriptor.js +13 -0
- package/lib/less/tree/unit.js +141 -0
- package/lib/less/tree/url.js +65 -0
- package/lib/less/tree/value.js +44 -0
- package/lib/less/tree/variable-call.js +46 -0
- package/lib/less/tree/variable.js +67 -0
- package/lib/less/utils.js +122 -0
- package/lib/less/visitors/extend-visitor.js +505 -0
- package/lib/less/visitors/import-sequencer.js +58 -0
- package/lib/less/visitors/import-visitor.js +189 -0
- package/lib/less/visitors/index.js +15 -0
- package/lib/less/visitors/join-selector-visitor.js +57 -0
- package/lib/less/visitors/set-tree-visibility-visitor.js +45 -0
- package/lib/less/visitors/to-css-visitor.js +363 -0
- package/lib/less/visitors/visitor.js +163 -0
- package/lib/less-browser/add-default-options.js +49 -0
- package/lib/less-browser/bootstrap.js +69 -0
- package/lib/less-browser/browser.js +65 -0
- package/lib/less-browser/cache.js +43 -0
- package/lib/less-browser/error-reporting.js +170 -0
- package/lib/less-browser/file-manager.js +113 -0
- package/lib/less-browser/image-size.js +28 -0
- package/lib/less-browser/index.js +285 -0
- package/lib/less-browser/log-listener.js +42 -0
- package/lib/less-browser/plugin-loader.js +26 -0
- package/lib/less-browser/utils.js +24 -0
- package/lib/less-node/environment.js +16 -0
- package/lib/less-node/file-manager.js +177 -0
- package/lib/less-node/fs.js +10 -0
- package/lib/less-node/image-size.js +58 -0
- package/lib/less-node/index.js +27 -0
- package/lib/less-node/lessc-helper.js +89 -0
- package/lib/less-node/plugin-loader.js +53 -0
- package/lib/less-node/url-file-manager.js +49 -0
- package/lib/lessc.js +557 -0
- package/lib/source-map/source-map-0.1.31.js +1933 -0
- package/lib/source-map/source-map-footer.js +4 -0
- package/lib/source-map/source-map-header.js +3 -0
- package/package.json +1 -1
- package/test/.DS_Store +0 -0
- package/test/browser/less.min.js +11 -0
- package/test/browser/less.min.js.map +1 -0
- package/test/css/css-escapes.css +1 -0
- package/test/less/css-escapes.less +3 -1
- package/.git/index +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import functionRegistry from '../functions/function-registry';
|
|
2
|
+
import LessError from '../less-error';
|
|
3
|
+
|
|
4
|
+
class AbstractPluginLoader {
|
|
5
|
+
constructor() {
|
|
6
|
+
// Implemented by Node.js plugin loader
|
|
7
|
+
this.require = () => null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
evalPlugin(contents, context, imports, pluginOptions, fileInfo) {
|
|
11
|
+
let loader;
|
|
12
|
+
let registry;
|
|
13
|
+
let pluginObj;
|
|
14
|
+
let localModule;
|
|
15
|
+
let pluginManager;
|
|
16
|
+
let filename;
|
|
17
|
+
let result;
|
|
18
|
+
|
|
19
|
+
pluginManager = context.pluginManager;
|
|
20
|
+
|
|
21
|
+
if (fileInfo) {
|
|
22
|
+
if (typeof fileInfo === 'string') {
|
|
23
|
+
filename = fileInfo;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
filename = fileInfo.filename;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const shortname = (new this.less.FileManager()).extractUrlParts(filename).filename;
|
|
30
|
+
|
|
31
|
+
if (filename) {
|
|
32
|
+
pluginObj = pluginManager.get(filename);
|
|
33
|
+
|
|
34
|
+
if (pluginObj) {
|
|
35
|
+
result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
|
|
36
|
+
if (result) {
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
if (pluginObj.use) {
|
|
41
|
+
pluginObj.use.call(this.context, pluginObj);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
e.message = e.message || 'Error during @plugin call';
|
|
46
|
+
return new LessError(e, imports, filename);
|
|
47
|
+
}
|
|
48
|
+
return pluginObj;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
localModule = {
|
|
52
|
+
exports: {},
|
|
53
|
+
pluginManager,
|
|
54
|
+
fileInfo
|
|
55
|
+
};
|
|
56
|
+
registry = functionRegistry.create();
|
|
57
|
+
|
|
58
|
+
const registerPlugin = obj => {
|
|
59
|
+
pluginObj = obj;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
loader = new Function('module', 'require', 'registerPlugin', 'functions', 'tree', 'less', 'fileInfo', contents);
|
|
64
|
+
loader(localModule, this.require(filename), registerPlugin, registry, this.less.tree, this.less, fileInfo);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
return new LessError(e, imports, filename);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!pluginObj) {
|
|
71
|
+
pluginObj = localModule.exports;
|
|
72
|
+
}
|
|
73
|
+
pluginObj = this.validatePlugin(pluginObj, filename, shortname);
|
|
74
|
+
|
|
75
|
+
if (pluginObj instanceof LessError) {
|
|
76
|
+
return pluginObj;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (pluginObj) {
|
|
80
|
+
pluginObj.imports = imports;
|
|
81
|
+
pluginObj.filename = filename;
|
|
82
|
+
|
|
83
|
+
// For < 3.x (or unspecified minVersion) - setOptions() before install()
|
|
84
|
+
if (!pluginObj.minVersion || this.compareVersion('3.0.0', pluginObj.minVersion) < 0) {
|
|
85
|
+
result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
|
|
86
|
+
|
|
87
|
+
if (result) {
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Run on first load
|
|
93
|
+
pluginManager.addPlugin(pluginObj, fileInfo.filename, registry);
|
|
94
|
+
pluginObj.functions = registry.getLocalFunctions();
|
|
95
|
+
|
|
96
|
+
// Need to call setOptions again because the pluginObj might have functions
|
|
97
|
+
result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
|
|
98
|
+
if (result) {
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Run every @plugin call
|
|
103
|
+
try {
|
|
104
|
+
if (pluginObj.use) {
|
|
105
|
+
pluginObj.use.call(this.context, pluginObj);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
e.message = e.message || 'Error during @plugin call';
|
|
110
|
+
return new LessError(e, imports, filename);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return new LessError({ message: 'Not a valid plugin' }, imports, filename);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return pluginObj;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
trySetOptions(plugin, filename, name, options) {
|
|
122
|
+
if (options && !plugin.setOptions) {
|
|
123
|
+
return new LessError({
|
|
124
|
+
message: `Options have been provided but the plugin ${name} does not support any options.`
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
plugin.setOptions && plugin.setOptions(options);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
return new LessError(e);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
validatePlugin(plugin, filename, name) {
|
|
136
|
+
if (plugin) {
|
|
137
|
+
// support plugins being a function
|
|
138
|
+
// so that the plugin can be more usable programmatically
|
|
139
|
+
if (typeof plugin === 'function') {
|
|
140
|
+
plugin = new plugin();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (plugin.minVersion) {
|
|
144
|
+
if (this.compareVersion(plugin.minVersion, this.less.version) < 0) {
|
|
145
|
+
return new LessError({
|
|
146
|
+
message: `Plugin ${name} requires version ${this.versionToString(plugin.minVersion)}`
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return plugin;
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
compareVersion(aVersion, bVersion) {
|
|
156
|
+
if (typeof aVersion === 'string') {
|
|
157
|
+
aVersion = aVersion.match(/^(\d+)\.?(\d+)?\.?(\d+)?/);
|
|
158
|
+
aVersion.shift();
|
|
159
|
+
}
|
|
160
|
+
for (let i = 0; i < aVersion.length; i++) {
|
|
161
|
+
if (aVersion[i] !== bVersion[i]) {
|
|
162
|
+
return parseInt(aVersion[i]) > parseInt(bVersion[i]) ? -1 : 1;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
versionToString(version) {
|
|
169
|
+
let versionString = '';
|
|
170
|
+
for (let i = 0; i < version.length; i++) {
|
|
171
|
+
versionString += (versionString ? '.' : '') + version[i];
|
|
172
|
+
}
|
|
173
|
+
return versionString;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
printUsage(plugins) {
|
|
177
|
+
for (let i = 0; i < plugins.length; i++) {
|
|
178
|
+
const plugin = plugins[i];
|
|
179
|
+
if (plugin.printUsage) {
|
|
180
|
+
plugin.printUsage();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export default AbstractPluginLoader;
|
|
187
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
/**
|
|
3
|
+
* Converts a string to a base 64 string
|
|
4
|
+
* @param str
|
|
5
|
+
*/
|
|
6
|
+
encodeBase64: function(str) {
|
|
7
|
+
},
|
|
8
|
+
/**
|
|
9
|
+
* Lookup the mime-type of a filename
|
|
10
|
+
* @param filename
|
|
11
|
+
*/
|
|
12
|
+
mimeLookup: function (filename) {
|
|
13
|
+
},
|
|
14
|
+
/**
|
|
15
|
+
* Look up the charset of a mime type
|
|
16
|
+
* @param mime
|
|
17
|
+
*/
|
|
18
|
+
charsetLookup: function (mime) {
|
|
19
|
+
},
|
|
20
|
+
/**
|
|
21
|
+
* Gets a source map generator
|
|
22
|
+
*/
|
|
23
|
+
getSourceMapGenerator: function getSourceMapGenerator() {
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @todo Document why this abstraction exists, and the relationship between
|
|
3
|
+
* environment, file managers, and plugin manager
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import logger from '../logger';
|
|
7
|
+
|
|
8
|
+
class environment {
|
|
9
|
+
constructor(externalEnvironment, fileManagers) {
|
|
10
|
+
this.fileManagers = fileManagers || [];
|
|
11
|
+
externalEnvironment = externalEnvironment || {};
|
|
12
|
+
|
|
13
|
+
const optionalFunctions = ['encodeBase64', 'mimeLookup', 'charsetLookup', 'getSourceMapGenerator'];
|
|
14
|
+
const requiredFunctions = [];
|
|
15
|
+
const functions = requiredFunctions.concat(optionalFunctions);
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < functions.length; i++) {
|
|
18
|
+
const propName = functions[i];
|
|
19
|
+
const environmentFunc = externalEnvironment[propName];
|
|
20
|
+
if (environmentFunc) {
|
|
21
|
+
this[propName] = environmentFunc.bind(externalEnvironment);
|
|
22
|
+
} else if (i < requiredFunctions.length) {
|
|
23
|
+
this.warn(`missing required function in environment - ${propName}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getFileManager(filename, currentDirectory, options, environment, isSync) {
|
|
29
|
+
|
|
30
|
+
if (!filename) {
|
|
31
|
+
logger.warn('getFileManager called with no filename.. Please report this issue. continuing.');
|
|
32
|
+
}
|
|
33
|
+
if (currentDirectory == null) {
|
|
34
|
+
logger.warn('getFileManager called with null directory.. Please report this issue. continuing.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let fileManagers = this.fileManagers;
|
|
38
|
+
if (options.pluginManager) {
|
|
39
|
+
fileManagers = [].concat(fileManagers).concat(options.pluginManager.getFileManagers());
|
|
40
|
+
}
|
|
41
|
+
for (let i = fileManagers.length - 1; i >= 0 ; i--) {
|
|
42
|
+
const fileManager = fileManagers[i];
|
|
43
|
+
if (fileManager[isSync ? 'supportsSync' : 'supports'](filename, currentDirectory, options, environment)) {
|
|
44
|
+
return fileManager;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
addFileManager(fileManager) {
|
|
51
|
+
this.fileManagers.push(fileManager);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
clearFileManagers() {
|
|
55
|
+
this.fileManagers = [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default environment;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
/**
|
|
3
|
+
* Given the full path to a file, return the path component
|
|
4
|
+
* Provided by AbstractFileManager
|
|
5
|
+
* @param {string} filename
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
getPath: function(filename) {
|
|
9
|
+
},
|
|
10
|
+
/**
|
|
11
|
+
* Append a .less extension if appropriate. Only called if less thinks one could be added.
|
|
12
|
+
* Provided by AbstractFileManager
|
|
13
|
+
* @param filename
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
tryAppendLessExtension: function(filename) {
|
|
17
|
+
},
|
|
18
|
+
/**
|
|
19
|
+
* Whether the rootpath should be converted to be absolute.
|
|
20
|
+
* The browser ovverides this to return true because urls must be absolute.
|
|
21
|
+
* Provided by AbstractFileManager (returns false)
|
|
22
|
+
* @returns {bool}
|
|
23
|
+
*/
|
|
24
|
+
alwaysMakePathsAbsolute: function() {
|
|
25
|
+
},
|
|
26
|
+
/**
|
|
27
|
+
* Returns whether a path is absolute
|
|
28
|
+
* Provided by AbstractFileManager
|
|
29
|
+
* @param {string} path
|
|
30
|
+
* @returns {bool}
|
|
31
|
+
*/
|
|
32
|
+
isPathAbsolute: function(path) {
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* joins together 2 paths
|
|
36
|
+
* Provided by AbstractFileManager
|
|
37
|
+
* @param {string} basePath
|
|
38
|
+
* @param {string} laterPath
|
|
39
|
+
*/
|
|
40
|
+
join: function(basePath, laterPath) {
|
|
41
|
+
},
|
|
42
|
+
/**
|
|
43
|
+
* Returns the difference between 2 paths
|
|
44
|
+
* E.g. url = a/ baseUrl = a/b/ returns ../
|
|
45
|
+
* url = a/b/ baseUrl = a/ returns b/
|
|
46
|
+
* Provided by AbstractFileManager
|
|
47
|
+
* @param {string} url
|
|
48
|
+
* @param {string} baseUrl
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
51
|
+
pathDiff: function(url, baseUrl) {
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Returns whether this file manager supports this file for syncronous file retrieval
|
|
55
|
+
* If true is returned, loadFileSync will then be called with the file.
|
|
56
|
+
* Provided by AbstractFileManager (returns false)
|
|
57
|
+
* @param {string} filename
|
|
58
|
+
* @param {string} currentDirectory
|
|
59
|
+
* @param {object} options
|
|
60
|
+
* @param {less.environment.environment} environment
|
|
61
|
+
* @returns {bool}
|
|
62
|
+
*/
|
|
63
|
+
supportsSync: function(filename, currentDirectory, options, environment) {
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param {string} filename
|
|
68
|
+
* @param {string} currentDirectory
|
|
69
|
+
* @param {object} options
|
|
70
|
+
* @param {less.environment.environment} environment
|
|
71
|
+
* @returns {bool}
|
|
72
|
+
*/
|
|
73
|
+
supports: function(filename, currentDirectory, options, environment) {
|
|
74
|
+
},
|
|
75
|
+
/**
|
|
76
|
+
* Loads a file asynchronously. Expects a promise that either rejects with an error or fulfills with an
|
|
77
|
+
* object containing
|
|
78
|
+
* { filename: - full resolved path to file
|
|
79
|
+
* contents: - the contents of the file, as a string }
|
|
80
|
+
*
|
|
81
|
+
* @param {string} filename
|
|
82
|
+
* @param {string} currentDirectory
|
|
83
|
+
* @param {object} options
|
|
84
|
+
* @param {less.environment.environment} environment
|
|
85
|
+
* @returns {Promise}
|
|
86
|
+
*/
|
|
87
|
+
loadFile: function(filename, currentDirectory, options, environment) {
|
|
88
|
+
},
|
|
89
|
+
/**
|
|
90
|
+
* Loads a file synchronously. Expects an immediate return with an object containing
|
|
91
|
+
* { error: - error object if an error occurs
|
|
92
|
+
* filename: - full resolved path to file
|
|
93
|
+
* contents: - the contents of the file, as a string }
|
|
94
|
+
*
|
|
95
|
+
* @param {string} filename
|
|
96
|
+
* @param {string} currentDirectory
|
|
97
|
+
* @param {object} options
|
|
98
|
+
* @param {less.environment.environment} environment
|
|
99
|
+
* @returns {object} should be an object containing error or contents and filename
|
|
100
|
+
*/
|
|
101
|
+
loadFileSync: function(filename, currentDirectory, options, environment) {
|
|
102
|
+
}
|
|
103
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Anonymous from '../tree/anonymous';
|
|
2
|
+
import Keyword from '../tree/keyword';
|
|
3
|
+
|
|
4
|
+
function boolean(condition) {
|
|
5
|
+
return condition ? Keyword.True : Keyword.False;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function If(condition, trueValue, falseValue) {
|
|
9
|
+
return condition ? trueValue
|
|
10
|
+
: (falseValue || new Anonymous);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default { boolean, 'if': If };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import Color from '../tree/color';
|
|
2
|
+
|
|
3
|
+
// Color Blending
|
|
4
|
+
// ref: http://www.w3.org/TR/compositing-1
|
|
5
|
+
|
|
6
|
+
function colorBlend(mode, color1, color2) {
|
|
7
|
+
const ab = color1.alpha; // result
|
|
8
|
+
|
|
9
|
+
let // backdrop
|
|
10
|
+
cb;
|
|
11
|
+
|
|
12
|
+
const as = color2.alpha;
|
|
13
|
+
|
|
14
|
+
let // source
|
|
15
|
+
cs;
|
|
16
|
+
|
|
17
|
+
let ar;
|
|
18
|
+
let cr;
|
|
19
|
+
const r = [];
|
|
20
|
+
|
|
21
|
+
ar = as + ab * (1 - as);
|
|
22
|
+
for (let i = 0; i < 3; i++) {
|
|
23
|
+
cb = color1.rgb[i] / 255;
|
|
24
|
+
cs = color2.rgb[i] / 255;
|
|
25
|
+
cr = mode(cb, cs);
|
|
26
|
+
if (ar) {
|
|
27
|
+
cr = (as * cs + ab * (cb -
|
|
28
|
+
as * (cb + cs - cr))) / ar;
|
|
29
|
+
}
|
|
30
|
+
r[i] = cr * 255;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return new Color(r, ar);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const colorBlendModeFunctions = {
|
|
37
|
+
multiply: function(cb, cs) {
|
|
38
|
+
return cb * cs;
|
|
39
|
+
},
|
|
40
|
+
screen: function(cb, cs) {
|
|
41
|
+
return cb + cs - cb * cs;
|
|
42
|
+
},
|
|
43
|
+
overlay: function(cb, cs) {
|
|
44
|
+
cb *= 2;
|
|
45
|
+
return (cb <= 1) ?
|
|
46
|
+
colorBlendModeFunctions.multiply(cb, cs) :
|
|
47
|
+
colorBlendModeFunctions.screen(cb - 1, cs);
|
|
48
|
+
},
|
|
49
|
+
softlight: function(cb, cs) {
|
|
50
|
+
let d = 1;
|
|
51
|
+
let e = cb;
|
|
52
|
+
if (cs > 0.5) {
|
|
53
|
+
e = 1;
|
|
54
|
+
d = (cb > 0.25) ? Math.sqrt(cb)
|
|
55
|
+
: ((16 * cb - 12) * cb + 4) * cb;
|
|
56
|
+
}
|
|
57
|
+
return cb - (1 - 2 * cs) * e * (d - cb);
|
|
58
|
+
},
|
|
59
|
+
hardlight: function(cb, cs) {
|
|
60
|
+
return colorBlendModeFunctions.overlay(cs, cb);
|
|
61
|
+
},
|
|
62
|
+
difference: function(cb, cs) {
|
|
63
|
+
return Math.abs(cb - cs);
|
|
64
|
+
},
|
|
65
|
+
exclusion: function(cb, cs) {
|
|
66
|
+
return cb + cs - 2 * cb * cs;
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// non-w3c functions:
|
|
70
|
+
average: function(cb, cs) {
|
|
71
|
+
return (cb + cs) / 2;
|
|
72
|
+
},
|
|
73
|
+
negation: function(cb, cs) {
|
|
74
|
+
return 1 - Math.abs(cb + cs - 1);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
for (const f in colorBlendModeFunctions) {
|
|
79
|
+
if (colorBlendModeFunctions.hasOwnProperty(f)) {
|
|
80
|
+
colorBlend[f] = colorBlend.bind(null, colorBlendModeFunctions[f]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default colorBlend;
|