less 4.8.1 → 5.0.0-alpha.1
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/README.md +19 -5
- package/bin/lessc +190 -630
- package/dist/less-node.cjs +398 -14282
- package/index.cjs +5 -2
- package/lib/index.js +164 -0
- package/lib/lessc-helper.js +52 -0
- package/lib/logger.js +76 -0
- package/lib/options.d.ts +46 -0
- package/lib/options.js +145 -0
- package/lib/types.js +20 -0
- package/lib/version.js +19 -0
- package/package.json +33 -40
- package/dist/less.cjs +0 -14929
- package/dist/less.js +0 -14929
- package/dist/less.min.js +0 -11
- package/dist/less.min.js.map +0 -1
- package/lib/less/constants.js +0 -13
- package/lib/less/contexts.js +0 -165
- package/lib/less/data/colors.js +0 -150
- package/lib/less/data/index.js +0 -4
- package/lib/less/data/unit-conversions.js +0 -21
- package/lib/less/default-options.js +0 -89
- package/lib/less/deprecation.js +0 -82
- package/lib/less/environment/abstract-file-manager.js +0 -140
- package/lib/less/environment/abstract-plugin-loader.js +0 -185
- package/lib/less/environment/environment-api.ts +0 -21
- package/lib/less/environment/environment.js +0 -59
- package/lib/less/environment/file-manager-api.ts +0 -77
- package/lib/less/functions/boolean.js +0 -29
- package/lib/less/functions/color-blending.js +0 -85
- package/lib/less/functions/color.js +0 -452
- package/lib/less/functions/data-uri.js +0 -74
- package/lib/less/functions/default.js +0 -26
- package/lib/less/functions/function-caller.js +0 -55
- package/lib/less/functions/function-registry.js +0 -36
- package/lib/less/functions/index.js +0 -35
- package/lib/less/functions/list.js +0 -158
- package/lib/less/functions/math-helper.js +0 -22
- package/lib/less/functions/math.js +0 -30
- package/lib/less/functions/number.js +0 -95
- package/lib/less/functions/string.js +0 -36
- package/lib/less/functions/style.js +0 -29
- package/lib/less/functions/svg.js +0 -87
- package/lib/less/functions/types.js +0 -70
- package/lib/less/import-manager.js +0 -183
- package/lib/less/index.js +0 -95
- package/lib/less/less-error.js +0 -166
- package/lib/less/logger.js +0 -34
- package/lib/less/parse-tree.js +0 -124
- package/lib/less/parse.js +0 -87
- package/lib/less/parser/parser-input.js +0 -400
- package/lib/less/parser/parser.js +0 -2894
- package/lib/less/plugin-manager.js +0 -168
- package/lib/less/render.js +0 -41
- package/lib/less/source-map-builder.js +0 -82
- package/lib/less/source-map-output.js +0 -151
- package/lib/less/transform-tree.js +0 -102
- package/lib/less/tree/anonymous.js +0 -57
- package/lib/less/tree/assignment.js +0 -48
- package/lib/less/tree/atrule-syntax.js +0 -8
- package/lib/less/tree/atrule.js +0 -340
- package/lib/less/tree/attribute.js +0 -63
- package/lib/less/tree/call.js +0 -132
- package/lib/less/tree/color.js +0 -285
- package/lib/less/tree/combinator.js +0 -38
- package/lib/less/tree/comment.js +0 -48
- package/lib/less/tree/condition.js +0 -65
- package/lib/less/tree/container.js +0 -104
- package/lib/less/tree/debug-info.js +0 -80
- package/lib/less/tree/declaration.js +0 -139
- package/lib/less/tree/detached-ruleset.js +0 -45
- package/lib/less/tree/dimension.js +0 -215
- package/lib/less/tree/element.js +0 -93
- package/lib/less/tree/expression.js +0 -100
- package/lib/less/tree/extend.js +0 -88
- package/lib/less/tree/import.js +0 -299
- package/lib/less/tree/index.js +0 -56
- package/lib/less/tree/javascript.js +0 -45
- package/lib/less/tree/js-eval-node.js +0 -74
- package/lib/less/tree/keyword.js +0 -28
- package/lib/less/tree/media.js +0 -90
- package/lib/less/tree/merge-rules.js +0 -47
- package/lib/less/tree/mixin-call.js +0 -283
- package/lib/less/tree/mixin-definition.js +0 -319
- package/lib/less/tree/namespace-value.js +0 -95
- package/lib/less/tree/negative.js +0 -37
- package/lib/less/tree/nested-at-rule.js +0 -198
- package/lib/less/tree/node.js +0 -310
- package/lib/less/tree/operation.js +0 -81
- package/lib/less/tree/paren.js +0 -41
- package/lib/less/tree/property.js +0 -96
- package/lib/less/tree/query-in-parens.js +0 -64
- package/lib/less/tree/quoted.js +0 -114
- package/lib/less/tree/ruleset.js +0 -1066
- package/lib/less/tree/selector.js +0 -201
- package/lib/less/tree/unicode-descriptor.js +0 -14
- package/lib/less/tree/unit.js +0 -170
- package/lib/less/tree/url.js +0 -83
- package/lib/less/tree/value.js +0 -60
- package/lib/less/tree/variable-call.js +0 -60
- package/lib/less/tree/variable.js +0 -85
- package/lib/less/utils.js +0 -126
- package/lib/less/visitors/extend-visitor.js +0 -505
- package/lib/less/visitors/import-sequencer.js +0 -56
- package/lib/less/visitors/import-visitor.js +0 -203
- package/lib/less/visitors/index.js +0 -15
- package/lib/less/visitors/join-selector-visitor.js +0 -65
- package/lib/less/visitors/set-tree-visibility-visitor.js +0 -57
- package/lib/less/visitors/to-css-visitor.js +0 -332
- package/lib/less/visitors/visitor.js +0 -165
- package/lib/less-browser/add-default-options.js +0 -53
- package/lib/less-browser/bootstrap.js +0 -67
- package/lib/less-browser/browser.js +0 -65
- package/lib/less-browser/cache.js +0 -43
- package/lib/less-browser/error-reporting.js +0 -170
- package/lib/less-browser/file-manager.js +0 -112
- package/lib/less-browser/image-size.js +0 -28
- package/lib/less-browser/index.js +0 -284
- package/lib/less-browser/log-listener.js +0 -42
- package/lib/less-browser/plugin-loader.js +0 -24
- package/lib/less-browser/utils.js +0 -30
- package/lib/less-node/environment.js +0 -43
- package/lib/less-node/file-manager.js +0 -156
- package/lib/less-node/fs.js +0 -14
- package/lib/less-node/image-size.js +0 -78
- package/lib/less-node/index.js +0 -31
- package/lib/less-node/lessc-helper.js +0 -95
- package/lib/less-node/plugin-loader.js +0 -62
- package/lib/less-node/url-file-manager.js +0 -60
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import contexts from './contexts.js';
|
|
2
|
-
import Parser from './parser/parser.js';
|
|
3
|
-
import LessError from './less-error.js';
|
|
4
|
-
import * as utils from './utils.js';
|
|
5
|
-
import logger from './logger.js';
|
|
6
|
-
|
|
7
|
-
export default function(environment) {
|
|
8
|
-
// FileInfo = {
|
|
9
|
-
// 'rewriteUrls' - option - whether to adjust URL's to be relative
|
|
10
|
-
// 'filename' - full resolved filename of current file
|
|
11
|
-
// 'rootpath' - path to append to normal URLs for this node
|
|
12
|
-
// 'currentDirectory' - path to the current file, absolute
|
|
13
|
-
// 'rootFilename' - filename of the base file
|
|
14
|
-
// 'entryPath' - absolute path to the entry file
|
|
15
|
-
// 'reference' - whether the file should not be output and only output parts that are referenced
|
|
16
|
-
|
|
17
|
-
class ImportManager {
|
|
18
|
-
constructor(less, context, rootFileInfo) {
|
|
19
|
-
this.less = less;
|
|
20
|
-
this.rootFilename = rootFileInfo.filename;
|
|
21
|
-
this.paths = context.paths || []; // Search paths, when importing
|
|
22
|
-
this.contents = {}; // map - filename to contents of all the files
|
|
23
|
-
this.contentsIgnoredChars = {}; // map - filename to lines at the beginning of each file to ignore
|
|
24
|
-
this.mime = context.mime;
|
|
25
|
-
this.error = null;
|
|
26
|
-
this.context = context;
|
|
27
|
-
// Deprecated? Unused outside of here, could be useful.
|
|
28
|
-
this.queue = []; // Files which haven't been imported yet
|
|
29
|
-
this.files = {}; // Holds the imported parse trees.
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Add an import to be imported
|
|
34
|
-
* @param path - the raw path
|
|
35
|
-
* @param tryAppendExtension - whether to try appending a file extension (.less or .js if the path has no extension)
|
|
36
|
-
* @param currentFileInfo - the current file info (used for instance to work out relative paths)
|
|
37
|
-
* @param importOptions - import options
|
|
38
|
-
* @param callback - callback for when it is imported
|
|
39
|
-
*/
|
|
40
|
-
push(path, tryAppendExtension, currentFileInfo, importOptions, callback) {
|
|
41
|
-
const importManager = this, pluginLoader = this.context.pluginManager.Loader;
|
|
42
|
-
|
|
43
|
-
this.queue.push(path);
|
|
44
|
-
|
|
45
|
-
const fileParsedFunc = function (e, root, fullPath) {
|
|
46
|
-
importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
|
|
47
|
-
|
|
48
|
-
const importedEqualsRoot = fullPath === importManager.rootFilename;
|
|
49
|
-
if (importOptions.optional && e) {
|
|
50
|
-
callback(null, {rules:[]}, false, null);
|
|
51
|
-
logger.info(`The file ${fullPath} was skipped because it was not found and the import was marked optional.`);
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
// Inline imports aren't cached here.
|
|
55
|
-
// If we start to cache them, please make sure they won't conflict with non-inline imports of the
|
|
56
|
-
// same name as they used to do before this comment and the condition below have been added.
|
|
57
|
-
if (!importManager.files[fullPath] && !importOptions.inline) {
|
|
58
|
-
importManager.files[fullPath] = { root, options: importOptions };
|
|
59
|
-
}
|
|
60
|
-
if (e && !importManager.error) { importManager.error = e; }
|
|
61
|
-
callback(e, root, importedEqualsRoot, fullPath);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const newFileInfo = {
|
|
66
|
-
rewriteUrls: this.context.rewriteUrls,
|
|
67
|
-
entryPath: currentFileInfo.entryPath,
|
|
68
|
-
rootpath: currentFileInfo.rootpath,
|
|
69
|
-
rootFilename: currentFileInfo.rootFilename
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment);
|
|
73
|
-
|
|
74
|
-
if (!fileManager) {
|
|
75
|
-
fileParsedFunc({ message: `Could not find a file-manager for ${path}` });
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const loadFileCallback = function(loadedFile) {
|
|
80
|
-
let plugin;
|
|
81
|
-
const resolvedFilename = loadedFile.filename;
|
|
82
|
-
const contents = loadedFile.contents.replace(/^\uFEFF/, '');
|
|
83
|
-
|
|
84
|
-
// Pass on an updated rootpath if path of imported file is relative and file
|
|
85
|
-
// is in a (sub|sup) directory
|
|
86
|
-
//
|
|
87
|
-
// Examples:
|
|
88
|
-
// - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
|
|
89
|
-
// then rootpath should become 'less/module/nav/'
|
|
90
|
-
// - If path of imported file is '../mixins.less' and rootpath is 'less/',
|
|
91
|
-
// then rootpath should become 'less/../'
|
|
92
|
-
newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
|
|
93
|
-
if (newFileInfo.rewriteUrls) {
|
|
94
|
-
newFileInfo.rootpath = fileManager.join(
|
|
95
|
-
(importManager.context.rootpath || ''),
|
|
96
|
-
fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
|
|
97
|
-
|
|
98
|
-
if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
|
|
99
|
-
newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
newFileInfo.filename = resolvedFilename;
|
|
103
|
-
|
|
104
|
-
const newEnv = new contexts.Parse(importManager.context);
|
|
105
|
-
|
|
106
|
-
newEnv.processImports = false;
|
|
107
|
-
importManager.contents[resolvedFilename] = contents;
|
|
108
|
-
|
|
109
|
-
if (currentFileInfo.reference || importOptions.reference) {
|
|
110
|
-
newFileInfo.reference = true;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (importOptions.isPlugin) {
|
|
114
|
-
plugin = pluginLoader.evalPlugin(contents, newEnv, importManager, importOptions.pluginArgs, newFileInfo);
|
|
115
|
-
if (plugin instanceof LessError) {
|
|
116
|
-
fileParsedFunc(plugin, null, resolvedFilename);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
fileParsedFunc(null, plugin, resolvedFilename);
|
|
120
|
-
}
|
|
121
|
-
} else if (importOptions.inline) {
|
|
122
|
-
fileParsedFunc(null, contents, resolvedFilename);
|
|
123
|
-
} else {
|
|
124
|
-
// import (multiple) parse trees apparently get altered and can't be cached.
|
|
125
|
-
// TODO: investigate why this is
|
|
126
|
-
if (importManager.files[resolvedFilename]
|
|
127
|
-
&& !importManager.files[resolvedFilename].options.multiple
|
|
128
|
-
&& !importOptions.multiple) {
|
|
129
|
-
|
|
130
|
-
fileParsedFunc(null, importManager.files[resolvedFilename].root, resolvedFilename);
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
|
|
134
|
-
fileParsedFunc(e, root, resolvedFilename);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
let loadedFile;
|
|
140
|
-
let promise;
|
|
141
|
-
const context = utils.clone(this.context);
|
|
142
|
-
|
|
143
|
-
if (tryAppendExtension) {
|
|
144
|
-
context.ext = importOptions.isPlugin ? '.js' : '.less';
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (importOptions.isPlugin) {
|
|
148
|
-
context.mime = 'application/javascript';
|
|
149
|
-
|
|
150
|
-
if (context.syncImport) {
|
|
151
|
-
loadedFile = pluginLoader.loadPluginSync(path, currentFileInfo.currentDirectory, context, environment, fileManager);
|
|
152
|
-
} else {
|
|
153
|
-
promise = pluginLoader.loadPlugin(path, currentFileInfo.currentDirectory, context, environment, fileManager);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
if (context.syncImport) {
|
|
158
|
-
loadedFile = fileManager.loadFileSync(path, currentFileInfo.currentDirectory, context, environment);
|
|
159
|
-
} else {
|
|
160
|
-
promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, context, environment,
|
|
161
|
-
(err, loadedFile) => {
|
|
162
|
-
if (err) {
|
|
163
|
-
fileParsedFunc(err);
|
|
164
|
-
} else {
|
|
165
|
-
loadFileCallback(loadedFile);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
if (loadedFile) {
|
|
171
|
-
if (!loadedFile.filename) {
|
|
172
|
-
fileParsedFunc(loadedFile);
|
|
173
|
-
} else {
|
|
174
|
-
loadFileCallback(loadedFile);
|
|
175
|
-
}
|
|
176
|
-
} else if (promise) {
|
|
177
|
-
promise.then(loadFileCallback, fileParsedFunc);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return ImportManager;
|
|
183
|
-
}
|
package/lib/less/index.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import Environment from './environment/environment.js';
|
|
2
|
-
import data from './data/index.js';
|
|
3
|
-
import tree from './tree/index.js';
|
|
4
|
-
import AbstractFileManager from './environment/abstract-file-manager.js';
|
|
5
|
-
import AbstractPluginLoader from './environment/abstract-plugin-loader.js';
|
|
6
|
-
import visitors from './visitors/index.js';
|
|
7
|
-
import Parser from './parser/parser.js';
|
|
8
|
-
import functions from './functions/index.js';
|
|
9
|
-
import contexts from './contexts.js';
|
|
10
|
-
import LessError from './less-error.js';
|
|
11
|
-
import transformTree from './transform-tree.js';
|
|
12
|
-
import * as utils from './utils.js';
|
|
13
|
-
import PluginManager from './plugin-manager.js';
|
|
14
|
-
import logger from './logger.js';
|
|
15
|
-
import SourceMapOutput from './source-map-output.js';
|
|
16
|
-
import SourceMapBuilder from './source-map-builder.js';
|
|
17
|
-
import ParseTree from './parse-tree.js';
|
|
18
|
-
import ImportManager from './import-manager.js';
|
|
19
|
-
import Parse from './parse.js';
|
|
20
|
-
import Render from './render.js';
|
|
21
|
-
import parseVersion from 'parse-node-version';
|
|
22
|
-
|
|
23
|
-
export default function(environment, fileManagers, version = '0.0.0') {
|
|
24
|
-
let sourceMapOutput, sourceMapBuilder, parseTree, importManager;
|
|
25
|
-
|
|
26
|
-
environment = new Environment(environment, fileManagers);
|
|
27
|
-
sourceMapOutput = SourceMapOutput(environment);
|
|
28
|
-
sourceMapBuilder = SourceMapBuilder(sourceMapOutput, environment);
|
|
29
|
-
parseTree = ParseTree(sourceMapBuilder);
|
|
30
|
-
importManager = ImportManager(environment);
|
|
31
|
-
|
|
32
|
-
const render = Render(environment, parseTree, importManager);
|
|
33
|
-
const parse = Parse(environment, parseTree, importManager);
|
|
34
|
-
|
|
35
|
-
const v = parseVersion(`v${version}`);
|
|
36
|
-
const initial = {
|
|
37
|
-
version: [v.major, v.minor, v.patch],
|
|
38
|
-
data,
|
|
39
|
-
tree,
|
|
40
|
-
Environment,
|
|
41
|
-
AbstractFileManager,
|
|
42
|
-
AbstractPluginLoader,
|
|
43
|
-
environment,
|
|
44
|
-
visitors,
|
|
45
|
-
Parser,
|
|
46
|
-
functions: functions(environment),
|
|
47
|
-
contexts,
|
|
48
|
-
SourceMapOutput: sourceMapOutput,
|
|
49
|
-
SourceMapBuilder: sourceMapBuilder,
|
|
50
|
-
ParseTree: parseTree,
|
|
51
|
-
ImportManager: importManager,
|
|
52
|
-
render,
|
|
53
|
-
parse,
|
|
54
|
-
LessError,
|
|
55
|
-
transformTree,
|
|
56
|
-
utils,
|
|
57
|
-
PluginManager,
|
|
58
|
-
logger
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// Create a public API
|
|
62
|
-
|
|
63
|
-
const ctor = function(t) {
|
|
64
|
-
return function(...args) {
|
|
65
|
-
return new t(...args);
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
let t;
|
|
69
|
-
const api = Object.create(initial);
|
|
70
|
-
for (const n in initial.tree) {
|
|
71
|
-
/* eslint guard-for-in: 0 */
|
|
72
|
-
t = initial.tree[n];
|
|
73
|
-
if (typeof t === 'function') {
|
|
74
|
-
api[n.toLowerCase()] = ctor(t);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
api[n] = Object.create(null);
|
|
78
|
-
for (const o in t) {
|
|
79
|
-
/* eslint guard-for-in: 0 */
|
|
80
|
-
api[n][o.toLowerCase()] = ctor(t[o]);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Some of the functions assume a `this` context of the API object,
|
|
87
|
-
* which causes it to fail when wrapped for ES6 imports.
|
|
88
|
-
*
|
|
89
|
-
* An assumed `this` should be removed in the future.
|
|
90
|
-
*/
|
|
91
|
-
initial.parse = initial.parse.bind(api);
|
|
92
|
-
initial.render = initial.render.bind(api);
|
|
93
|
-
|
|
94
|
-
return api;
|
|
95
|
-
}
|
package/lib/less/less-error.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import * as utils from './utils.js';
|
|
2
|
-
|
|
3
|
-
const anonymousFunc = /(<anonymous>|Function):(\d+):(\d+)/;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* This is a centralized class of any error that could be thrown internally (mostly by the parser).
|
|
7
|
-
* Besides standard .message it keeps some additional data like a path to the file where the error
|
|
8
|
-
* occurred along with line and column numbers.
|
|
9
|
-
*
|
|
10
|
-
* @class
|
|
11
|
-
* @extends Error
|
|
12
|
-
* @type {module.LessError}
|
|
13
|
-
*
|
|
14
|
-
* @prop {string} type
|
|
15
|
-
* @prop {string} filename
|
|
16
|
-
* @prop {number} index
|
|
17
|
-
* @prop {number} line
|
|
18
|
-
* @prop {number} column
|
|
19
|
-
* @prop {number} callLine
|
|
20
|
-
* @prop {number} callExtract
|
|
21
|
-
* @prop {string[]} extract
|
|
22
|
-
*
|
|
23
|
-
* @param {Object} e - An error object to wrap around or just a descriptive object
|
|
24
|
-
* @param {Object} fileContentMap - An object with file contents in 'contents' property (like importManager) @todo - move to fileManager?
|
|
25
|
-
* @param {string} [currentFilename]
|
|
26
|
-
*/
|
|
27
|
-
const LessError = function(e, fileContentMap, currentFilename) {
|
|
28
|
-
Error.call(this);
|
|
29
|
-
|
|
30
|
-
const filename = e.filename || currentFilename;
|
|
31
|
-
|
|
32
|
-
this.message = e.message;
|
|
33
|
-
this.stack = e.stack;
|
|
34
|
-
|
|
35
|
-
// Set type early so it's always available, even if fileContentMap is missing
|
|
36
|
-
this.type = e.type || 'Syntax';
|
|
37
|
-
|
|
38
|
-
if (fileContentMap && filename) {
|
|
39
|
-
const input = fileContentMap.contents[filename];
|
|
40
|
-
const loc = utils.getLocation(e.index, input);
|
|
41
|
-
var line = loc.line;
|
|
42
|
-
const col = loc.column;
|
|
43
|
-
const callLine = e.call && utils.getLocation(e.call, input).line;
|
|
44
|
-
const lines = input ? input.split('\n') : '';
|
|
45
|
-
|
|
46
|
-
this.filename = filename;
|
|
47
|
-
this.index = e.index;
|
|
48
|
-
this.line = typeof line === 'number' ? line + 1 : null;
|
|
49
|
-
this.column = col;
|
|
50
|
-
|
|
51
|
-
if (!this.line && this.stack) {
|
|
52
|
-
const found = this.stack.match(anonymousFunc);
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* We have to figure out how this environment stringifies anonymous functions
|
|
56
|
-
* so we can correctly map plugin errors.
|
|
57
|
-
*
|
|
58
|
-
* Note, in Node 8, the output of anonymous funcs varied based on parameters
|
|
59
|
-
* being present or not, so we inject dummy params.
|
|
60
|
-
*/
|
|
61
|
-
const func = new Function('a', 'throw new Error()');
|
|
62
|
-
let lineAdjust = 0;
|
|
63
|
-
try {
|
|
64
|
-
func();
|
|
65
|
-
} catch (e) {
|
|
66
|
-
const match = e.stack.match(anonymousFunc);
|
|
67
|
-
lineAdjust = 1 - parseInt(match[2]);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (found) {
|
|
71
|
-
if (found[2]) {
|
|
72
|
-
this.line = parseInt(found[2]) + lineAdjust;
|
|
73
|
-
}
|
|
74
|
-
if (found[3]) {
|
|
75
|
-
this.column = parseInt(found[3]);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
this.callLine = callLine + 1;
|
|
81
|
-
this.callExtract = lines[callLine];
|
|
82
|
-
|
|
83
|
-
this.extract = [
|
|
84
|
-
lines[this.line - 2],
|
|
85
|
-
lines[this.line - 1],
|
|
86
|
-
lines[this.line]
|
|
87
|
-
];
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
if (typeof Object.create === 'undefined') {
|
|
93
|
-
const F = function () {};
|
|
94
|
-
F.prototype = Error.prototype;
|
|
95
|
-
LessError.prototype = new F();
|
|
96
|
-
} else {
|
|
97
|
-
LessError.prototype = Object.create(Error.prototype);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
LessError.prototype.constructor = LessError;
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* An overridden version of the default Object.prototype.toString
|
|
104
|
-
* which uses additional information to create a helpful message.
|
|
105
|
-
*
|
|
106
|
-
* @param {Object} options
|
|
107
|
-
* @returns {string}
|
|
108
|
-
*/
|
|
109
|
-
LessError.prototype.toString = function(options) {
|
|
110
|
-
options = options || {};
|
|
111
|
-
const isWarning = (this.type ?? '').toLowerCase().includes('warning');
|
|
112
|
-
const type = isWarning ? this.type : `${this.type}Error`;
|
|
113
|
-
const color = isWarning ? 'yellow' : 'red';
|
|
114
|
-
|
|
115
|
-
let message = '';
|
|
116
|
-
const extract = this.extract || [];
|
|
117
|
-
let error = [];
|
|
118
|
-
let stylize = function (str) { return str; };
|
|
119
|
-
if (options.stylize) {
|
|
120
|
-
const type = typeof options.stylize;
|
|
121
|
-
if (type !== 'function') {
|
|
122
|
-
throw Error(`options.stylize should be a function, got a ${type}!`);
|
|
123
|
-
}
|
|
124
|
-
stylize = options.stylize;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (this.line !== null) {
|
|
128
|
-
if (!isWarning && typeof extract[0] === 'string') {
|
|
129
|
-
error.push(stylize(`${this.line - 1} ${extract[0]}`, 'grey'));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (typeof extract[1] === 'string') {
|
|
133
|
-
let errorTxt = `${this.line} `;
|
|
134
|
-
if (extract[1]) {
|
|
135
|
-
errorTxt += extract[1].slice(0, this.column) +
|
|
136
|
-
stylize(stylize(stylize(extract[1].slice(this.column, this.column + 1), 'bold') +
|
|
137
|
-
extract[1].slice(this.column + 1), 'red'), 'inverse');
|
|
138
|
-
}
|
|
139
|
-
error.push(errorTxt);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (!isWarning && typeof extract[2] === 'string') {
|
|
143
|
-
error.push(stylize(`${this.line + 1} ${extract[2]}`, 'grey'));
|
|
144
|
-
}
|
|
145
|
-
error = `${error.join('\n') + stylize('', 'reset')}\n`;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
message += stylize(`${type}: ${this.message}`, color);
|
|
149
|
-
if (this.filename) {
|
|
150
|
-
message += stylize(' in ', color) + this.filename;
|
|
151
|
-
}
|
|
152
|
-
if (this.line) {
|
|
153
|
-
message += stylize(` on line ${this.line}, column ${this.column + 1}:`, 'grey');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
message += `\n${error}`;
|
|
157
|
-
|
|
158
|
-
if (this.callLine) {
|
|
159
|
-
message += `${stylize('from ', color) + (this.filename || '')}/n`;
|
|
160
|
-
message += `${stylize(this.callLine, 'grey')} ${this.callExtract}/n`;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return message;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
export default LessError;
|
package/lib/less/logger.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
error: function(msg) {
|
|
3
|
-
this._fireEvent('error', msg);
|
|
4
|
-
},
|
|
5
|
-
warn: function(msg) {
|
|
6
|
-
this._fireEvent('warn', msg);
|
|
7
|
-
},
|
|
8
|
-
info: function(msg) {
|
|
9
|
-
this._fireEvent('info', msg);
|
|
10
|
-
},
|
|
11
|
-
debug: function(msg) {
|
|
12
|
-
this._fireEvent('debug', msg);
|
|
13
|
-
},
|
|
14
|
-
addListener: function(listener) {
|
|
15
|
-
this._listeners.push(listener);
|
|
16
|
-
},
|
|
17
|
-
removeListener: function(listener) {
|
|
18
|
-
for (let i = 0; i < this._listeners.length; i++) {
|
|
19
|
-
if (this._listeners[i] === listener) {
|
|
20
|
-
this._listeners.splice(i, 1);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
_fireEvent: function(type, msg) {
|
|
26
|
-
for (let i = 0; i < this._listeners.length; i++) {
|
|
27
|
-
const logFunction = this._listeners[i][type];
|
|
28
|
-
if (logFunction) {
|
|
29
|
-
logFunction(msg);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
_listeners: []
|
|
34
|
-
};
|
package/lib/less/parse-tree.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import LessError from './less-error.js';
|
|
2
|
-
import transformTree from './transform-tree.js';
|
|
3
|
-
import logger from './logger.js';
|
|
4
|
-
|
|
5
|
-
export default function(SourceMapBuilder) {
|
|
6
|
-
class ParseTree {
|
|
7
|
-
constructor(root, imports) {
|
|
8
|
-
this.root = root;
|
|
9
|
-
this.imports = imports;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
toCSS(options) {
|
|
13
|
-
let evaldRoot;
|
|
14
|
-
const result = {};
|
|
15
|
-
let sourceMapBuilder;
|
|
16
|
-
try {
|
|
17
|
-
evaldRoot = transformTree(this.root, options);
|
|
18
|
-
} catch (e) {
|
|
19
|
-
throw new LessError(e, this.imports);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const compress = Boolean(options.compress);
|
|
24
|
-
if (compress) {
|
|
25
|
-
logger.warn('The compress option has been deprecated. ' +
|
|
26
|
-
'We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const toCSSOptions = {
|
|
30
|
-
compress,
|
|
31
|
-
// @deprecated The dumpLineNumbers option is deprecated. Use sourcemaps instead. All modes will be removed in a future version.
|
|
32
|
-
dumpLineNumbers: options.dumpLineNumbers,
|
|
33
|
-
strictUnits: Boolean(options.strictUnits),
|
|
34
|
-
numPrecision: 8};
|
|
35
|
-
|
|
36
|
-
if (options.sourceMap) {
|
|
37
|
-
// Normalize sourceMap option: if it's just true, convert to object
|
|
38
|
-
if (options.sourceMap === true) {
|
|
39
|
-
options.sourceMap = {};
|
|
40
|
-
}
|
|
41
|
-
const sourceMapOpts = options.sourceMap;
|
|
42
|
-
|
|
43
|
-
// Set sourceMapInputFilename if not set and filename is available
|
|
44
|
-
if (!sourceMapOpts.sourceMapInputFilename && options.filename) {
|
|
45
|
-
sourceMapOpts.sourceMapInputFilename = options.filename;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Default sourceMapBasepath to the input file's directory if not set
|
|
49
|
-
// This matches the behavior documented and implemented in bin/lessc
|
|
50
|
-
if (sourceMapOpts.sourceMapBasepath === undefined && options.filename) {
|
|
51
|
-
// Get directory from filename using string manipulation (works cross-platform)
|
|
52
|
-
const lastSlash = Math.max(options.filename.lastIndexOf('/'), options.filename.lastIndexOf('\\'));
|
|
53
|
-
if (lastSlash >= 0) {
|
|
54
|
-
sourceMapOpts.sourceMapBasepath = options.filename.substring(0, lastSlash);
|
|
55
|
-
} else {
|
|
56
|
-
// No directory separator found, use current directory
|
|
57
|
-
sourceMapOpts.sourceMapBasepath = '.';
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Handle sourceMapFullFilename (CLI-specific: --source-map=filename)
|
|
62
|
-
// This is converted to sourceMapFilename and sourceMapOutputFilename
|
|
63
|
-
if (sourceMapOpts.sourceMapFullFilename && !sourceMapOpts.sourceMapFileInline) {
|
|
64
|
-
// This case is handled by lessc before calling render
|
|
65
|
-
// We just need to ensure sourceMapFilename is set if sourceMapFullFilename is provided
|
|
66
|
-
if (!sourceMapOpts.sourceMapFilename && !sourceMapOpts.sourceMapURL) {
|
|
67
|
-
// Extract just the basename for the sourceMappingURL comment
|
|
68
|
-
const mapBase = sourceMapOpts.sourceMapFullFilename.split(/[/\\]/).pop();
|
|
69
|
-
sourceMapOpts.sourceMapFilename = mapBase;
|
|
70
|
-
}
|
|
71
|
-
} else if (!sourceMapOpts.sourceMapFilename && !sourceMapOpts.sourceMapURL) {
|
|
72
|
-
// If sourceMapFilename is not set and sourceMapURL is not set,
|
|
73
|
-
// derive it from the output filename (if available) or input filename
|
|
74
|
-
if (sourceMapOpts.sourceMapOutputFilename) {
|
|
75
|
-
// Use output filename + .map
|
|
76
|
-
sourceMapOpts.sourceMapFilename = sourceMapOpts.sourceMapOutputFilename + '.map';
|
|
77
|
-
} else if (options.filename) {
|
|
78
|
-
// Fallback to input filename + .css.map (basename only)
|
|
79
|
-
const inputBasename = options.filename.split(/[/\\]/).pop().replace(/\.[^/.]+$/, '');
|
|
80
|
-
sourceMapOpts.sourceMapFilename = inputBasename + '.css.map';
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Default sourceMapOutputFilename if not set
|
|
85
|
-
if (!sourceMapOpts.sourceMapOutputFilename) {
|
|
86
|
-
if (options.filename) {
|
|
87
|
-
const inputBasename = options.filename.split(/[/\\]/).pop().replace(/\.[^/.]+$/, '');
|
|
88
|
-
sourceMapOpts.sourceMapOutputFilename = inputBasename + '.css';
|
|
89
|
-
} else {
|
|
90
|
-
sourceMapOpts.sourceMapOutputFilename = 'output.css';
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
sourceMapBuilder = new SourceMapBuilder(sourceMapOpts);
|
|
95
|
-
result.css = sourceMapBuilder.toCSS(evaldRoot, toCSSOptions, this.imports);
|
|
96
|
-
} else {
|
|
97
|
-
result.css = evaldRoot.toCSS(toCSSOptions);
|
|
98
|
-
}
|
|
99
|
-
} catch (e) {
|
|
100
|
-
throw new LessError(e, this.imports);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (options.pluginManager) {
|
|
104
|
-
const postProcessors = options.pluginManager.getPostProcessors();
|
|
105
|
-
for (let i = 0; i < postProcessors.length; i++) {
|
|
106
|
-
result.css = postProcessors[i].process(result.css, { sourceMap: sourceMapBuilder, options, imports: this.imports });
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (options.sourceMap) {
|
|
110
|
-
result.map = sourceMapBuilder.getExternalSourceMap();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
result.imports = [];
|
|
114
|
-
for (const file in this.imports.files) {
|
|
115
|
-
if (Object.prototype.hasOwnProperty.call(this.imports.files, file) && file !== this.imports.rootFilename) {
|
|
116
|
-
result.imports.push(file);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return ParseTree;
|
|
124
|
-
}
|
package/lib/less/parse.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import contexts from './contexts.js';
|
|
2
|
-
import Parser from './parser/parser.js';
|
|
3
|
-
import PluginManager from './plugin-manager.js';
|
|
4
|
-
import LessError from './less-error.js';
|
|
5
|
-
import * as utils from './utils.js';
|
|
6
|
-
|
|
7
|
-
export default function(environment, ParseTree, ImportManager) {
|
|
8
|
-
const parse = function (input, options, callback) {
|
|
9
|
-
|
|
10
|
-
if (typeof options === 'function') {
|
|
11
|
-
callback = options;
|
|
12
|
-
options = utils.copyOptions(this.options, {});
|
|
13
|
-
}
|
|
14
|
-
else {
|
|
15
|
-
options = utils.copyOptions(this.options, options || {});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (!callback) {
|
|
19
|
-
const self = this;
|
|
20
|
-
return new Promise(function (resolve, reject) {
|
|
21
|
-
parse.call(self, input, options, function(err, output) {
|
|
22
|
-
if (err) {
|
|
23
|
-
reject(err);
|
|
24
|
-
} else {
|
|
25
|
-
resolve(output);
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
} else {
|
|
30
|
-
let context;
|
|
31
|
-
let rootFileInfo;
|
|
32
|
-
const pluginManager = new PluginManager(this, !options.reUsePluginManager);
|
|
33
|
-
|
|
34
|
-
options.pluginManager = pluginManager;
|
|
35
|
-
|
|
36
|
-
context = new contexts.Parse(options);
|
|
37
|
-
|
|
38
|
-
if (options.rootFileInfo) {
|
|
39
|
-
rootFileInfo = options.rootFileInfo;
|
|
40
|
-
} else {
|
|
41
|
-
const filename = options.filename || 'input';
|
|
42
|
-
const entryPath = filename.replace(/[^/\\]*$/, '');
|
|
43
|
-
rootFileInfo = {
|
|
44
|
-
filename,
|
|
45
|
-
rewriteUrls: context.rewriteUrls,
|
|
46
|
-
rootpath: context.rootpath || '',
|
|
47
|
-
currentDirectory: entryPath,
|
|
48
|
-
entryPath,
|
|
49
|
-
rootFilename: filename
|
|
50
|
-
};
|
|
51
|
-
// add in a missing trailing slash
|
|
52
|
-
if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== '/') {
|
|
53
|
-
rootFileInfo.rootpath += '/';
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const imports = new ImportManager(this, context, rootFileInfo);
|
|
58
|
-
this.importManager = imports;
|
|
59
|
-
|
|
60
|
-
// TODO: allow the plugins to be just a list of paths or names
|
|
61
|
-
// Do an async plugin queue like lessc
|
|
62
|
-
|
|
63
|
-
if (options.plugins) {
|
|
64
|
-
options.plugins.forEach(function(plugin) {
|
|
65
|
-
let evalResult, contents;
|
|
66
|
-
if (plugin.fileContent) {
|
|
67
|
-
contents = plugin.fileContent.replace(/^\uFEFF/, '');
|
|
68
|
-
evalResult = pluginManager.Loader.evalPlugin(contents, context, imports, plugin.options, plugin.filename);
|
|
69
|
-
if (evalResult instanceof LessError) {
|
|
70
|
-
return callback(evalResult);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
pluginManager.addPlugin(plugin);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
new Parser(context, imports, rootFileInfo)
|
|
80
|
-
.parse(input, function (e, root) {
|
|
81
|
-
if (e) { return callback(e); }
|
|
82
|
-
callback(null, root, imports, options);
|
|
83
|
-
}, options);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
return parse;
|
|
87
|
-
}
|