less 5.0.0-alpha.1 → 5.0.0-alpha.11
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 +10 -6
- package/V5-STATUS.md +71 -0
- package/bin/lessc +130 -14
- package/dist/less-browser-dev.js +2550 -0
- package/dist/less-node.cjs +193 -100
- package/lib/browser-dev.js +86 -0
- package/lib/lessc-helper.js +15 -3
- package/lib/options.d.ts +39 -3
- package/lib/options.js +104 -22
- package/package.json +14 -12
package/dist/less-node.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Less - Leaner CSS v5.0.0-alpha.
|
|
2
|
+
* Less - Leaner CSS v5.0.0-alpha.11
|
|
3
3
|
* http://lesscss.org
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) 2009-2026, Alexis Sellier <self@cloudhead.net>
|
|
@@ -18,8 +18,8 @@ var compiler = require('@jesscss/compiler');
|
|
|
18
18
|
var nodeModulesPlugin = require('@jesscss/plugin-node-modules');
|
|
19
19
|
var lessPlugin = require('@jesscss/plugin-less');
|
|
20
20
|
var pluginLessCompat = require('@jesscss/plugin-less-compat');
|
|
21
|
-
var parseNodeVersion = require('parse-node-version');
|
|
22
21
|
var core = require('@jesscss/core');
|
|
22
|
+
var parseNodeVersion = require('parse-node-version');
|
|
23
23
|
|
|
24
24
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
25
25
|
|
|
@@ -27,31 +27,94 @@ var nodeModulesPlugin__default = /*#__PURE__*/_interopDefaultLegacy(nodeModulesP
|
|
|
27
27
|
var lessPlugin__default = /*#__PURE__*/_interopDefaultLegacy(lessPlugin);
|
|
28
28
|
var parseNodeVersion__default = /*#__PURE__*/_interopDefaultLegacy(parseNodeVersion);
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Less logger wired to Jess's logger singleton.
|
|
32
|
+
* Forwards to Jess and maintains Less-style addListener/removeListener for compatibility.
|
|
33
|
+
* @module less/lib/logger
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** @typedef {{ error?: (msg: string) => void, warn?: (msg: string) => void, info?: (msg: string) => void, debug?: (msg: string) => void }} LogListener */
|
|
37
|
+
|
|
38
|
+
/** @type {LogListener[]} */
|
|
39
|
+
const _listeners = [];
|
|
40
|
+
|
|
41
|
+
/** @param {'error'|'warn'|'info'|'debug'} type @param {string} msg */
|
|
42
|
+
function _fireEvent(type, msg) {
|
|
43
|
+
for (const listener of _listeners) {
|
|
44
|
+
const fn = listener[type];
|
|
45
|
+
if (fn) fn(msg);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Wrap Jess's logger so Less listeners receive Jess's log output without
|
|
50
|
+
// writing directly to stderr/stdout. Library consumers should be able to catch
|
|
51
|
+
// `less.render()` rejections without surprise terminal output; the CLI owns
|
|
52
|
+
// deciding whether/how to print diagnostics.
|
|
53
|
+
core.logger.configure?.({
|
|
54
|
+
log(...args) {
|
|
55
|
+
_fireEvent('debug', args.map(String).join(' '));
|
|
56
|
+
},
|
|
57
|
+
info(...args) {
|
|
58
|
+
_fireEvent('info', args.map(String).join(' '));
|
|
59
|
+
},
|
|
60
|
+
warn(...args) {
|
|
61
|
+
_fireEvent('warn', args.map(String).join(' '));
|
|
62
|
+
},
|
|
63
|
+
error(...args) {
|
|
64
|
+
_fireEvent('error', args.map(String).join(' '));
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/** Less-compatible logger backed by Jess's singleton */
|
|
69
|
+
const logger = {
|
|
70
|
+
/** @param {string} msg */
|
|
71
|
+
error(msg) {
|
|
72
|
+
_fireEvent('error', msg);
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
/** @param {string} msg */
|
|
76
|
+
warn(msg) {
|
|
77
|
+
_fireEvent('warn', msg);
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/** @param {string} msg */
|
|
81
|
+
info(msg) {
|
|
82
|
+
_fireEvent('info', msg);
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/** @param {string} msg */
|
|
86
|
+
debug(msg) {
|
|
87
|
+
_fireEvent('debug', msg);
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
/** @param {LogListener} listener */
|
|
91
|
+
addListener(listener) {
|
|
92
|
+
_listeners.push(listener);
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
/** @param {LogListener} listener */
|
|
96
|
+
removeListener(listener) {
|
|
97
|
+
const i = _listeners.indexOf(listener);
|
|
98
|
+
if (i >= 0) _listeners.splice(i, 1);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
|
|
30
102
|
/**
|
|
31
103
|
* Options mapping between Less render options and Jess compiler config.
|
|
32
104
|
* @module less/lib/options
|
|
33
105
|
*/
|
|
34
106
|
|
|
35
107
|
const unsupportedAlphaOptions = new Map([
|
|
36
|
-
['sourceMap', 'source maps are not supported'],
|
|
37
|
-
['sourceMapFilename', 'source maps are not supported'],
|
|
38
|
-
['sourceMapRootpath', 'source maps are not supported'],
|
|
39
|
-
['sourceMapBasepath', 'source maps are not supported'],
|
|
40
|
-
['sourceMapURL', 'source maps are not supported'],
|
|
41
|
-
['sourceMapFileInline', 'source maps are not supported'],
|
|
42
108
|
['globalVars', 'global variable injection is not supported'],
|
|
43
109
|
['modifyVars', 'modify-var injection is not supported'],
|
|
44
|
-
['strictUnits', 'strict unit mode is not supported'],
|
|
45
|
-
['rootpath', 'URL rootpath rewriting is not supported'],
|
|
46
|
-
['rewriteUrls', 'URL rewriting is not supported'],
|
|
47
|
-
['urlArgs', 'URL argument rewriting is not supported'],
|
|
48
110
|
['javascriptEnabled', 'JavaScript evaluation is not supported'],
|
|
49
|
-
['compress', 'compressed output is not supported'],
|
|
50
111
|
]);
|
|
51
112
|
|
|
52
113
|
function validateAlphaOptions(options) {
|
|
53
114
|
for (const [name, reason] of unsupportedAlphaOptions) {
|
|
54
|
-
|
|
115
|
+
// A falsy value is the 4.x default ("off") and requests nothing, so it is
|
|
116
|
+
// a no-op here; only an actual request for the feature is unsupported.
|
|
117
|
+
if (options[name]) {
|
|
55
118
|
throw new Error(`${name} is not supported: ${reason}`);
|
|
56
119
|
}
|
|
57
120
|
}
|
|
@@ -88,6 +151,55 @@ function stableStringify(value, seen = new WeakSet()) {
|
|
|
88
151
|
return `{${entries.join(',')}}`;
|
|
89
152
|
}
|
|
90
153
|
|
|
154
|
+
/**
|
|
155
|
+
* `collapseNesting` accepts `false` (keep authored nesting — the v5 default),
|
|
156
|
+
* `'native'` (CSS Nesting desugaring: parent wrapped in `:is()`, child selector
|
|
157
|
+
* lists distributed, specificity-faithful), `'compact'` (like `'native'` but
|
|
158
|
+
* also folds same-combinator descendant runs into one `:is()`), or the
|
|
159
|
+
* deprecated boolean `true` (alias for `'native'`). Anything else is rejected.
|
|
160
|
+
* @param {unknown} value
|
|
161
|
+
* @returns {boolean|'native'|'compact'}
|
|
162
|
+
*/
|
|
163
|
+
function resolveCollapseNesting(value) {
|
|
164
|
+
if (value === false || value === true || value === 'native' || value === 'compact') {
|
|
165
|
+
return value;
|
|
166
|
+
}
|
|
167
|
+
throw new Error(
|
|
168
|
+
`collapseNesting must be false, 'native', 'compact', or true `
|
|
169
|
+
+ `(deprecated alias for 'native'); got ${JSON.stringify(value)}`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Build the compiler's `output.sourceMap` value from Less options. Source maps
|
|
175
|
+
* are enabled when `sourceMap` is truthy; the object form (or the flat legacy
|
|
176
|
+
* `sourceMap*` options) configures the details. Returns `undefined` when no
|
|
177
|
+
* source map is requested.
|
|
178
|
+
* @param {import('./options.js').LessRenderOptions} opts
|
|
179
|
+
* @returns {undefined | true | Record<string, unknown>}
|
|
180
|
+
*/
|
|
181
|
+
function resolveSourceMap(opts) {
|
|
182
|
+
if (!opts.sourceMap) {
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
const config = (typeof opts.sourceMap === 'object' && opts.sourceMap !== null)
|
|
186
|
+
? { ...opts.sourceMap }
|
|
187
|
+
: {};
|
|
188
|
+
// Fold the flat legacy `sourceMap*` options into the object form the compiler
|
|
189
|
+
// reads; an explicit object sub-option wins over its flat alias.
|
|
190
|
+
const flat = [
|
|
191
|
+
'sourceMapURL', 'sourceMapFilename', 'sourceMapFullFilename',
|
|
192
|
+
'sourceMapRootpath', 'sourceMapBasepath', 'sourceMapFileInline',
|
|
193
|
+
'sourceMapOutputFilename', 'outputSourceFiles', 'disableSourcemapAnnotation'
|
|
194
|
+
];
|
|
195
|
+
for (const key of flat) {
|
|
196
|
+
if (opts[key] !== undefined && config[key] === undefined) {
|
|
197
|
+
config[key] = opts[key];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return Object.keys(config).length > 0 ? config : true;
|
|
201
|
+
}
|
|
202
|
+
|
|
91
203
|
/**
|
|
92
204
|
* Map Less render options to Jess compiler config.
|
|
93
205
|
* @param {import('./options.js').LessRenderOptions} [options] Less-style options
|
|
@@ -107,26 +219,60 @@ function createLessOptions(options) {
|
|
|
107
219
|
math === 2 || math === 'parens' || math === 'strict' ? 'parens' :
|
|
108
220
|
'parens-division';
|
|
109
221
|
|
|
110
|
-
|
|
222
|
+
// `unitMode` is the option ('loose' | 'preserve' | 'strict'); `strictUnits`
|
|
223
|
+
// is its deprecated boolean alias: true → 'strict'; false means "not strict",
|
|
224
|
+
// i.e. the default ('preserve') — never the Less 4.x 'loose' fold, which only
|
|
225
|
+
// an explicit `unitMode: 'loose'` selects. Any use warns so the mapping is
|
|
226
|
+
// never discovered by staring at output. Left unset so the compiler default applies.
|
|
227
|
+
const unitMode = opts.unitMode !== undefined ? opts.unitMode
|
|
228
|
+
: opts.strictUnits === true ? 'strict'
|
|
229
|
+
: undefined;
|
|
230
|
+
if (opts.strictUnits !== undefined && opts.unitMode === undefined) {
|
|
231
|
+
logger.warn(
|
|
232
|
+
`strictUnits is deprecated; use unitMode. strictUnits: ${String(opts.strictUnits)} now means `
|
|
233
|
+
+ `unitMode: '${unitMode ?? 'preserve'}'${opts.strictUnits ? '' : " (Less 4.x unit folding is unitMode: 'loose')"}`
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// URL rewriting lives on the Less plugin (it rewrites `url(...)` during
|
|
238
|
+
// serialization), not in `output`. Only forward keys the caller set so the
|
|
239
|
+
// plugin's own v5 defaults apply otherwise.
|
|
240
|
+
const lessPluginOptions = {};
|
|
241
|
+
if (opts.rootpath !== undefined) lessPluginOptions.rootpath = opts.rootpath;
|
|
242
|
+
if (opts.rewriteUrls !== undefined) lessPluginOptions.rewriteUrls = opts.rewriteUrls;
|
|
243
|
+
if (opts.urlArgs !== undefined) lessPluginOptions.urlArgs = opts.urlArgs;
|
|
244
|
+
|
|
245
|
+
const plugins = [lessPlugin__default["default"](lessPluginOptions)];
|
|
111
246
|
if (!skipLessCompat) {
|
|
112
247
|
plugins.push(pluginLessCompat.lessCompatPlugin({ plugins: lessPlugins }));
|
|
113
248
|
}
|
|
114
249
|
|
|
250
|
+
// The projection/serialization options the compiler reads off `output`:
|
|
251
|
+
// `collapseNesting` (nesting flatten mode), `compress` (minified output), and
|
|
252
|
+
// `sourceMap`. Emitted as a single file-less array entry so an explicit render
|
|
253
|
+
// option overrides a file-local styles.config for every key (the config merge
|
|
254
|
+
// appends it as the override default); left `{}` when the caller set none.
|
|
255
|
+
const outputEntry = {};
|
|
256
|
+
if (opts.collapseNesting !== undefined) {
|
|
257
|
+
outputEntry.collapseNesting = resolveCollapseNesting(opts.collapseNesting);
|
|
258
|
+
}
|
|
259
|
+
if (opts.compress !== undefined) {
|
|
260
|
+
outputEntry.compress = opts.compress;
|
|
261
|
+
}
|
|
262
|
+
const sourceMap = resolveSourceMap(opts);
|
|
263
|
+
if (sourceMap !== undefined) {
|
|
264
|
+
outputEntry.sourceMap = sourceMap;
|
|
265
|
+
}
|
|
266
|
+
const output = Object.keys(outputEntry).length > 0 ? [outputEntry] : {};
|
|
267
|
+
|
|
115
268
|
const configOptions = {
|
|
116
269
|
compile: {
|
|
117
270
|
searchPaths: opts.paths || [],
|
|
118
271
|
mathMode,
|
|
272
|
+
...(unitMode !== undefined && { unitMode }),
|
|
119
273
|
plugins,
|
|
120
274
|
},
|
|
121
|
-
|
|
122
|
-
// switch requests flattened CSS. Keep that public Less option at the
|
|
123
|
-
// wrapper boundary; Jess owns the one renderer and its output mode.
|
|
124
|
-
// A file's styles.config may use an output array. A file-less output entry
|
|
125
|
-
// is the compiler's documented per-render override for that shape, so an
|
|
126
|
-
// explicit public Less option remains authoritative over fixture config.
|
|
127
|
-
output: Object.prototype.hasOwnProperty.call(opts, 'collapseNesting')
|
|
128
|
-
? [{ collapseNesting: opts.collapseNesting === true }]
|
|
129
|
-
: {},
|
|
275
|
+
output,
|
|
130
276
|
language: {},
|
|
131
277
|
};
|
|
132
278
|
|
|
@@ -154,6 +300,13 @@ function mapRenderResult(result, options) {
|
|
|
154
300
|
css: result.css ?? '',
|
|
155
301
|
};
|
|
156
302
|
|
|
303
|
+
// Less 4.x returns the source map as `result.map` (a JSON string) when one was
|
|
304
|
+
// requested; forward it so `less.render(src, { sourceMap: true })` behaves the
|
|
305
|
+
// same. The compiler writes the `sourceMappingURL` annotation into `css` itself.
|
|
306
|
+
if (result.map !== undefined) {
|
|
307
|
+
out.map = result.map;
|
|
308
|
+
}
|
|
309
|
+
|
|
157
310
|
if (result.imports && Array.isArray(result.imports)) {
|
|
158
311
|
out.imports = result.imports;
|
|
159
312
|
}
|
|
@@ -172,7 +325,7 @@ function mapRenderResult(result, options) {
|
|
|
172
325
|
* @module less/lib/version
|
|
173
326
|
*/
|
|
174
327
|
|
|
175
|
-
const semver = "5.0.0-alpha.
|
|
328
|
+
const semver = "5.0.0-alpha.11";
|
|
176
329
|
const parsed = parseNodeVersion__default["default"](`v${semver}`);
|
|
177
330
|
|
|
178
331
|
const version = {
|
|
@@ -180,78 +333,6 @@ const version = {
|
|
|
180
333
|
array: [parsed.major, parsed.minor, parsed.patch],
|
|
181
334
|
};
|
|
182
335
|
|
|
183
|
-
/**
|
|
184
|
-
* Less logger wired to Jess's logger singleton.
|
|
185
|
-
* Forwards to Jess and maintains Less-style addListener/removeListener for compatibility.
|
|
186
|
-
* @module less/lib/logger
|
|
187
|
-
*/
|
|
188
|
-
|
|
189
|
-
/** @typedef {{ error?: (msg: string) => void, warn?: (msg: string) => void, info?: (msg: string) => void, debug?: (msg: string) => void }} LogListener */
|
|
190
|
-
|
|
191
|
-
/** @type {LogListener[]} */
|
|
192
|
-
const _listeners = [];
|
|
193
|
-
|
|
194
|
-
/** @param {'error'|'warn'|'info'|'debug'} type @param {string} msg */
|
|
195
|
-
function _fireEvent(type, msg) {
|
|
196
|
-
for (const listener of _listeners) {
|
|
197
|
-
const fn = listener[type];
|
|
198
|
-
if (fn) fn(msg);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Wrap Jess's logger so Less listeners receive Jess's log output without
|
|
203
|
-
// writing directly to stderr/stdout. Library consumers should be able to catch
|
|
204
|
-
// `less.render()` rejections without surprise terminal output; the CLI owns
|
|
205
|
-
// deciding whether/how to print diagnostics.
|
|
206
|
-
core.logger.configure?.({
|
|
207
|
-
log(...args) {
|
|
208
|
-
_fireEvent('debug', args.map(String).join(' '));
|
|
209
|
-
},
|
|
210
|
-
info(...args) {
|
|
211
|
-
_fireEvent('info', args.map(String).join(' '));
|
|
212
|
-
},
|
|
213
|
-
warn(...args) {
|
|
214
|
-
_fireEvent('warn', args.map(String).join(' '));
|
|
215
|
-
},
|
|
216
|
-
error(...args) {
|
|
217
|
-
_fireEvent('error', args.map(String).join(' '));
|
|
218
|
-
},
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
/** Less-compatible logger backed by Jess's singleton */
|
|
222
|
-
const logger = {
|
|
223
|
-
/** @param {string} msg */
|
|
224
|
-
error(msg) {
|
|
225
|
-
_fireEvent('error', msg);
|
|
226
|
-
},
|
|
227
|
-
|
|
228
|
-
/** @param {string} msg */
|
|
229
|
-
warn(msg) {
|
|
230
|
-
_fireEvent('warn', msg);
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
/** @param {string} msg */
|
|
234
|
-
info(msg) {
|
|
235
|
-
_fireEvent('info', msg);
|
|
236
|
-
},
|
|
237
|
-
|
|
238
|
-
/** @param {string} msg */
|
|
239
|
-
debug(msg) {
|
|
240
|
-
_fireEvent('debug', msg);
|
|
241
|
-
},
|
|
242
|
-
|
|
243
|
-
/** @param {LogListener} listener */
|
|
244
|
-
addListener(listener) {
|
|
245
|
-
_listeners.push(listener);
|
|
246
|
-
},
|
|
247
|
-
|
|
248
|
-
/** @param {LogListener} listener */
|
|
249
|
-
removeListener(listener) {
|
|
250
|
-
const i = _listeners.indexOf(listener);
|
|
251
|
-
if (i >= 0) _listeners.splice(i, 1);
|
|
252
|
-
},
|
|
253
|
-
};
|
|
254
|
-
|
|
255
336
|
/**
|
|
256
337
|
* Helper functions for lessc CLI.
|
|
257
338
|
* Adapted from lib.bak/less-node/lessc-helper.js.
|
|
@@ -291,11 +372,23 @@ const lesscHelper = {
|
|
|
291
372
|
console.log(' --quiet Suppresses output of warnings.');
|
|
292
373
|
console.log(' -v, --version Prints version number and exit.');
|
|
293
374
|
console.log(' --verbose Be verbose.');
|
|
294
|
-
console.log(' --collapse-nesting
|
|
375
|
+
console.log(' --collapse-nesting[=MODE] Flatten nested rules: native (default), or compact.');
|
|
376
|
+
console.log(' -x, --compress Compress output by removing whitespace.');
|
|
377
|
+
console.log(' --math=MODE Math mode: parens-division (default), always, or parens.');
|
|
378
|
+
console.log(' --unit-mode=MODE Unit handling in math: preserve (default), strict, or loose (Less 4.x guessing).');
|
|
379
|
+
console.log(' --strict-units[=on|off] Deprecated: on is --unit-mode=strict, off is the default (preserve).');
|
|
380
|
+
console.log(' --source-map[=FILE] Emit a source map (FILE, or <destination>.map by default).');
|
|
381
|
+
console.log(' --source-map-inline Embed the source map as a data URI instead of a file.');
|
|
382
|
+
console.log(' --source-map-include-source Embed the source files in the map (sourcesContent).');
|
|
383
|
+
console.log(' --source-map-rootpath=PATH Prepend PATH to every source in the map.');
|
|
384
|
+
console.log(' --source-map-basepath=PATH Strip PATH from the front of every source in the map.');
|
|
385
|
+
console.log(' --source-map-url=URL Override the sourceMappingURL annotation.');
|
|
386
|
+
console.log(' --rewrite-urls[=all|local|off] Rewrite url(...) references in imported files.');
|
|
387
|
+
console.log(' --rootpath=PATH Prepend PATH to url(...) and import references.');
|
|
388
|
+
console.log(' --url-args=ARGS Append ARGS (e.g. cache-buster) to every url(...).');
|
|
295
389
|
console.log('');
|
|
296
390
|
console.log('This release intentionally supports a smaller CLI surface.');
|
|
297
|
-
console.log('
|
|
298
|
-
console.log('URL rewrite flags will be revisited in later alphas.');
|
|
391
|
+
console.log('Browser compilation, legacy plugin flags, and lint-only mode are not supported.');
|
|
299
392
|
console.log('');
|
|
300
393
|
console.log('Report bugs to: http://github.com/less/less.js/issues');
|
|
301
394
|
console.log('Home page: <http://lesscss.org/>');
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Less.js v5 — browser build (powered by Jess).
|
|
3
|
+
*
|
|
4
|
+
* A single-file, in-browser Less→CSS compiler. It drives `@jesscss/compiler`'s
|
|
5
|
+
* `renderToResult` with an inline `source` and NO `filePath`, so the Node-only
|
|
6
|
+
* config-discovery layer (cosmiconfig/env-paths/fs) is never reached. `@import`
|
|
7
|
+
* / file access is unsupported here (see build/browser-stubs/fs.js).
|
|
8
|
+
*
|
|
9
|
+
* Bundled to an IIFE that defines `window.less` with the same public shape as
|
|
10
|
+
* the Less 4.x browser build: `less.render(input, options?, callback?)` returns
|
|
11
|
+
* a Promise and also invokes the err-first callback when one is given.
|
|
12
|
+
*
|
|
13
|
+
* @module less/browser-dev
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { Compiler } from '@jesscss/compiler';
|
|
17
|
+
import { createLessOptions, mapRenderResult } from './options.js';
|
|
18
|
+
|
|
19
|
+
/* Injected at build time from packages/less/package.json. */
|
|
20
|
+
/* global __LESS_VERSION__ */
|
|
21
|
+
const semver = typeof __LESS_VERSION__ === 'string' ? __LESS_VERSION__ : '5.0.0-alpha.0';
|
|
22
|
+
const versionArray = semver.split('.').map((n) => parseInt(n, 10) || 0).slice(0, 3);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Build a Less-4.x-shaped error from the first Jess diagnostic. No fs fallback:
|
|
26
|
+
* in the browser there is no file to re-read for the source extract.
|
|
27
|
+
* @param {import('./options.js').JessRenderResult} result
|
|
28
|
+
*/
|
|
29
|
+
function createRenderError(result) {
|
|
30
|
+
const diagnostic = (result?.errors || [])[0];
|
|
31
|
+
const error = new Error(diagnostic?.message || 'Less render failed');
|
|
32
|
+
error.type = diagnostic?.phase || 'Syntax';
|
|
33
|
+
error.filename = diagnostic?.filePath || 'input';
|
|
34
|
+
error.line = diagnostic?.line || 1;
|
|
35
|
+
error.column = diagnostic?.column || 1;
|
|
36
|
+
const lines = diagnostic?.lines;
|
|
37
|
+
error.extract = Array.isArray(lines) ? lines.map(String) : undefined;
|
|
38
|
+
error.jessErrors = result?.errors || [];
|
|
39
|
+
error.jessWarnings = result?.warnings || [];
|
|
40
|
+
return error;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Render Less source to CSS. Mirrors the Less 4.x API: `options` and `callback`
|
|
45
|
+
* are both optional, `callback` may be passed as the second argument, and the
|
|
46
|
+
* returned Promise resolves to a `{ css, warnings }` result. When a callback is
|
|
47
|
+
* given it is invoked err-first and the Promise is still returned.
|
|
48
|
+
* @param {string} input Less source
|
|
49
|
+
* @param {object|Function} [options] Less-style options (math, collapseNesting, plugins) — or the callback
|
|
50
|
+
* @param {Function} [callback] err-first `(error, result)` callback
|
|
51
|
+
* @returns {Promise<{ css: string, warnings?: unknown[] }>}
|
|
52
|
+
*/
|
|
53
|
+
function render(input, options, callback) {
|
|
54
|
+
if (typeof options === 'function') {
|
|
55
|
+
callback = options;
|
|
56
|
+
options = {};
|
|
57
|
+
}
|
|
58
|
+
options = options || {};
|
|
59
|
+
const promise = (async () => {
|
|
60
|
+
const { configOptions } = createLessOptions(options);
|
|
61
|
+
// ponytail: fresh Compiler per call — no defaultPlugins hook, so no
|
|
62
|
+
// node-modules import plugin and no @jesscss/plugin-js. Single-file preview
|
|
63
|
+
// rarely re-renders in a hot loop; a cache map is not worth the surface.
|
|
64
|
+
const compiler = new Compiler(configOptions);
|
|
65
|
+
const result = await compiler.renderToResult(
|
|
66
|
+
{ source: input, language: 'less', extension: '.less' },
|
|
67
|
+
{ ...configOptions, suppressWarnings: true }
|
|
68
|
+
);
|
|
69
|
+
if (result.errors?.length) {
|
|
70
|
+
throw createRenderError(result);
|
|
71
|
+
}
|
|
72
|
+
return mapRenderResult(result, options);
|
|
73
|
+
})();
|
|
74
|
+
if (typeof callback === 'function') {
|
|
75
|
+
promise.then((result) => callback(null, result), (error) => callback(error));
|
|
76
|
+
}
|
|
77
|
+
return promise;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const less = {
|
|
81
|
+
version: versionArray,
|
|
82
|
+
render,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default less;
|
|
86
|
+
export { render, versionArray as version };
|
package/lib/lessc-helper.js
CHANGED
|
@@ -37,11 +37,23 @@ const lesscHelper = {
|
|
|
37
37
|
console.log(' --quiet Suppresses output of warnings.');
|
|
38
38
|
console.log(' -v, --version Prints version number and exit.');
|
|
39
39
|
console.log(' --verbose Be verbose.');
|
|
40
|
-
console.log(' --collapse-nesting
|
|
40
|
+
console.log(' --collapse-nesting[=MODE] Flatten nested rules: native (default), or compact.');
|
|
41
|
+
console.log(' -x, --compress Compress output by removing whitespace.');
|
|
42
|
+
console.log(' --math=MODE Math mode: parens-division (default), always, or parens.');
|
|
43
|
+
console.log(' --unit-mode=MODE Unit handling in math: preserve (default), strict, or loose (Less 4.x guessing).');
|
|
44
|
+
console.log(' --strict-units[=on|off] Deprecated: on is --unit-mode=strict, off is the default (preserve).');
|
|
45
|
+
console.log(' --source-map[=FILE] Emit a source map (FILE, or <destination>.map by default).');
|
|
46
|
+
console.log(' --source-map-inline Embed the source map as a data URI instead of a file.');
|
|
47
|
+
console.log(' --source-map-include-source Embed the source files in the map (sourcesContent).');
|
|
48
|
+
console.log(' --source-map-rootpath=PATH Prepend PATH to every source in the map.');
|
|
49
|
+
console.log(' --source-map-basepath=PATH Strip PATH from the front of every source in the map.');
|
|
50
|
+
console.log(' --source-map-url=URL Override the sourceMappingURL annotation.');
|
|
51
|
+
console.log(' --rewrite-urls[=all|local|off] Rewrite url(...) references in imported files.');
|
|
52
|
+
console.log(' --rootpath=PATH Prepend PATH to url(...) and import references.');
|
|
53
|
+
console.log(' --url-args=ARGS Append ARGS (e.g. cache-buster) to every url(...).');
|
|
41
54
|
console.log('');
|
|
42
55
|
console.log('This release intentionally supports a smaller CLI surface.');
|
|
43
|
-
console.log('
|
|
44
|
-
console.log('URL rewrite flags will be revisited in later alphas.');
|
|
56
|
+
console.log('Browser compilation, legacy plugin flags, and lint-only mode are not supported.');
|
|
45
57
|
console.log('');
|
|
46
58
|
console.log('Report bugs to: http://github.com/less/less.js/issues');
|
|
47
59
|
console.log('Home page: <http://lesscss.org/>');
|
package/lib/options.d.ts
CHANGED
|
@@ -13,10 +13,46 @@ export interface LessRenderOptions {
|
|
|
13
13
|
plugins?: unknown[];
|
|
14
14
|
math?: number | 'always' | 'parens-division' | 'parens' | 'strict';
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* How to flatten authored nesting. Less v5 preserves authored nesting by
|
|
17
|
+
* default (`false`). `'native'` applies the CSS Nesting desugaring (parent
|
|
18
|
+
* wrapped in `:is()`, child selector lists distributed — specificity-faithful,
|
|
19
|
+
* matching the browser and Less 4.x); `'compact'` additionally folds
|
|
20
|
+
* same-combinator descendant runs into a single `:is()`. `true` is a
|
|
21
|
+
* deprecated alias for `'native'`.
|
|
18
22
|
*/
|
|
19
|
-
collapseNesting?: boolean;
|
|
23
|
+
collapseNesting?: boolean | 'native' | 'compact';
|
|
24
|
+
/** Minified output. */
|
|
25
|
+
compress?: boolean;
|
|
26
|
+
/** Prepend a path to every rewritten `url(...)` and imported reference. */
|
|
27
|
+
rootpath?: string;
|
|
28
|
+
/** Rewrite relative `url(...)` against the importing file: `'all'` | `'local'` | `'off'` (or boolean). */
|
|
29
|
+
rewriteUrls?: boolean | 'all' | 'local' | 'off';
|
|
30
|
+
/** Append a query string to every non-data `url(...)`. */
|
|
31
|
+
urlArgs?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Emit a source map. `true` turns it on with defaults; the object form (or the
|
|
34
|
+
* flat legacy `sourceMap*` options) configures it. Returned as `result.map`.
|
|
35
|
+
*/
|
|
36
|
+
sourceMap?: boolean | {
|
|
37
|
+
sourceMapURL?: string;
|
|
38
|
+
sourceMapFilename?: string;
|
|
39
|
+
sourceMapFullFilename?: string;
|
|
40
|
+
sourceMapRootpath?: string;
|
|
41
|
+
sourceMapBasepath?: string;
|
|
42
|
+
sourceMapFileInline?: boolean;
|
|
43
|
+
sourceMapOutputFilename?: string;
|
|
44
|
+
outputSourceFiles?: boolean;
|
|
45
|
+
disableSourcemapAnnotation?: boolean;
|
|
46
|
+
};
|
|
47
|
+
sourceMapURL?: string;
|
|
48
|
+
sourceMapFilename?: string;
|
|
49
|
+
sourceMapFullFilename?: string;
|
|
50
|
+
sourceMapRootpath?: string;
|
|
51
|
+
sourceMapBasepath?: string;
|
|
52
|
+
sourceMapFileInline?: boolean;
|
|
53
|
+
sourceMapOutputFilename?: string;
|
|
54
|
+
outputSourceFiles?: boolean;
|
|
55
|
+
disableSourcemapAnnotation?: boolean;
|
|
20
56
|
/** @internal Jess alpha benchmark-only flag for source graphs already proven @plugin-free. */
|
|
21
57
|
__jessSkipLessCompatWhenPluginFree?: boolean;
|
|
22
58
|
}
|