mirror of
https://github.com/less/less.js.git
synced 2026-01-09 23:38:06 -05:00
✨ feat: deprecation warnings for Less + monorepo chores (#4319)
* Added deprecation warnings * Remove warning about combinator * Switch to PNPM * Update local dependencies * Remove inner dist folder * Create symbolic link to dist folder * Flip dist folders * Create symbolic link in root * Add contributors * 👥 Add @matthew-dean as a contributor * 👥 Add @cloudhead as a contributor * 👥 Add @lukeapage as a contributor * 👥 Add @seven-phases-max as a contributor * 👥 Add @iChenLei as a contributor * 👥 Add @puckowski as a contributor * Add more contributors * Finish deprecation warnings * Resolve deletions and such * Fix symbolic link * Update ci.yml to use PNPM * Update ci.yml to use PNPM * Refine CI versions * Fix node printed version * Better fix for #4258 and #4292 * Re-enable other tests
This commit is contained in:
77
.all-contributorsrc
Normal file
77
.all-contributorsrc
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"projectName": "Less.js",
|
||||
"projectOwner": "The Less CSS Team",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com/less/less.js",
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 100,
|
||||
"commit": true,
|
||||
"commitConvention": "gitmoji",
|
||||
"contributors": [
|
||||
{
|
||||
"login": "matthew-dean",
|
||||
"name": "Matthew Dean",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/414752?v=4",
|
||||
"profile": "https://github.com/matthew-dean",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"maintenance",
|
||||
"projectManagement"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cloudhead",
|
||||
"name": "Alexis Sellier",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/40774?v=4",
|
||||
"profile": "https://cloudhead.io/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lukeapage",
|
||||
"name": "Luke Page",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/309321?v=4",
|
||||
"profile": "https://github.com/lukeapage",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "seven-phases-max",
|
||||
"name": "Max Mikhailov",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5304376?v=4",
|
||||
"profile": "https://github.com/seven-phases-max",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "iChenLei",
|
||||
"name": "Lei Chen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/14012511?v=4",
|
||||
"profile": "https://github.com/iChenLei",
|
||||
"contributions": [
|
||||
"code",
|
||||
"bug",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "puckowski",
|
||||
"name": "Daniel Puckowski",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3059609?v=4",
|
||||
"profile": "https://github.com/puckowski",
|
||||
"contributions": [
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"linkToUsage": true
|
||||
}
|
||||
110
.github/workflows/ci.yml
vendored
110
.github/workflows/ci.yml
vendored
@@ -9,86 +9,40 @@ on:
|
||||
branches: [main, master]
|
||||
|
||||
jobs:
|
||||
basic_node_test:
|
||||
name: 'Basic tests on ubuntu-latest with nodejs v22 (current LTS version)'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- name: Install npm dependencies
|
||||
run: npm install
|
||||
- name: Print put node & npm version
|
||||
run: node --version && npm --version
|
||||
- name: Install chromium
|
||||
run: npx playwright install chromium
|
||||
- name: Run unit test
|
||||
run: npm run test
|
||||
|
||||
windows_and_macos_test:
|
||||
name: 'Platform tests on ${{matrix.os}} with nodejs v${{matrix.node}}'
|
||||
needs: basic_node_test
|
||||
test:
|
||||
name: 'Tests on ${{matrix.os}} with Node "${{matrix.node}}"'
|
||||
strategy:
|
||||
matrix:
|
||||
# Test all mainstream operating system
|
||||
os: [macos-latest, windows-latest]
|
||||
node: [22]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
# Pull repo to test machine
|
||||
- uses: actions/checkout@v2
|
||||
# Configures the node version used on GitHub-hosted runners
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
# The Node.js version to configure
|
||||
node-version: ${{ matrix.node }}
|
||||
- name: Install npm dependencies
|
||||
run: npm install
|
||||
- name: Print put node & npm version
|
||||
# Output useful info for debugging.
|
||||
run: node --version && npm --version
|
||||
- name: Install chromium
|
||||
run: npx playwright install chromium
|
||||
- name: Run unit test
|
||||
run: npm run test
|
||||
# Test all mainstream operating systems
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
node: ['current']
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
node: 'lts/*'
|
||||
- os: ubuntu-latest
|
||||
node: 'lts/-1'
|
||||
- os: ubuntu-latest
|
||||
node: 'lts/-2'
|
||||
- os: ubuntu-latest
|
||||
node: 'lts/-3'
|
||||
|
||||
historical_versions_node_test:
|
||||
name: 'Historical version nodejs v${{matrix.node}} test'
|
||||
needs: basic_node_test
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
node: [14, 16, 18, 20]
|
||||
runs-on: ${{ matrix.os }}
|
||||
# This has copy/paste steps and should be refactored using DRY
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- name: Install npm dependencies
|
||||
run: npm install
|
||||
- name: Print put node & npm version
|
||||
run: node --version && npm --version
|
||||
- name: Install chromium
|
||||
run: npx playwright install chromium
|
||||
- name: Run unit test
|
||||
run: npm run test
|
||||
|
||||
latest_nodejs_testing_node23:
|
||||
name: 'Latest nodejs v23 test'
|
||||
needs: basic_node_test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 23
|
||||
- name: Install npm dependencies
|
||||
run: npm install
|
||||
- name: Print put node & npm version
|
||||
run: node --version && npm --version
|
||||
- name: Install chromium
|
||||
run: npx playwright install chromium
|
||||
- name: Run unit test
|
||||
run: npm run test
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: 'pnpm'
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- name: Print put node & npm version
|
||||
run: node --version && pnpm --version
|
||||
- name: Install chromium
|
||||
run: npx playwright install chromium
|
||||
- name: Run unit test
|
||||
run: pnpm run test
|
||||
|
||||
@@ -25,7 +25,7 @@ Please report documentation issues in [the documentation project](https://github
|
||||
|
||||
* Please search for existing feature requests first to see if something similar already exists.
|
||||
* Include a clear and specific use-case. We love new ideas, but we do not add language features without a reason.
|
||||
* Consider whether or not your language feature would be better as a function or implemented in a 3rd-party build system such as [assemble-less](http://github.com/assemble/assemble-less).
|
||||
* Consider whether or not your language feature would be better as a function or implemented in a 3rd-party build system
|
||||
|
||||
|
||||
## Pull Requests
|
||||
@@ -51,15 +51,4 @@ Learn more about [developing Less.js](http://lesscss.org/usage/#developing-less)
|
||||
|
||||
## Releases
|
||||
|
||||
Releases are managed using Lerna. First, we determine if the release is a major (breaking), minor (new features), or patch (bug fix) change.
|
||||
|
||||
Then, you can run Lerna with a command like:
|
||||
```
|
||||
npx lerna version minor
|
||||
```
|
||||
|
||||
To publish, run the Lerna command for publishing without incrementing the version, as in:
|
||||
```
|
||||
npx lerna publish from-package --no-private
|
||||
```
|
||||
|
||||
Releases are managed using PNPM. Instructions TBD
|
||||
|
||||
35
README.md
35
README.md
@@ -1,4 +1,7 @@
|
||||
<p align="center"><img src="http://lesscss.org/public/img/less_logo.png" width="264" height="117">
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/less/less.js/actions?query=branch%3Amaster"><img src="https://github.com/less/less.js/actions/workflows/ci.yml/badge.svg?branch=master" alt="Github Actions CI"/></a>
|
||||
@@ -39,11 +42,39 @@ See the [changelog](CHANGELOG.md)
|
||||
|
||||
## Contributors
|
||||
|
||||
### Code Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
<a href="https://github.com/less/less.js/graphs/contributors"><img src="https://opencollective.com/less/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/matthew-dean"><img src="https://avatars.githubusercontent.com/u/414752?v=4?s=100" width="100px;" alt="Matthew Dean"/><br /><sub><b>Matthew Dean</b></sub></a><br /><a href="https://github.com/The Less CSS Team/Less.js/commits?author=matthew-dean" title="Code">💻</a> <a href="https://github.com/The Less CSS Team/Less.js/commits?author=matthew-dean" title="Documentation">📖</a> <a href="#maintenance-matthew-dean" title="Maintenance">🚧</a> <a href="#projectManagement-matthew-dean" title="Project Management">📆</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://cloudhead.io/"><img src="https://avatars.githubusercontent.com/u/40774?v=4?s=100" width="100px;" alt="Alexis Sellier"/><br /><sub><b>Alexis Sellier</b></sub></a><br /><a href="https://github.com/The Less CSS Team/Less.js/commits?author=cloudhead" title="Code">💻</a> <a href="https://github.com/The Less CSS Team/Less.js/commits?author=cloudhead" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lukeapage"><img src="https://avatars.githubusercontent.com/u/309321?v=4?s=100" width="100px;" alt="Luke Page"/><br /><sub><b>Luke Page</b></sub></a><br /><a href="https://github.com/The Less CSS Team/Less.js/commits?author=lukeapage" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/seven-phases-max"><img src="https://avatars.githubusercontent.com/u/5304376?v=4?s=100" width="100px;" alt="Max Mikhailov"/><br /><sub><b>Max Mikhailov</b></sub></a><br /><a href="https://github.com/The Less CSS Team/Less.js/commits?author=seven-phases-max" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/iChenLei"><img src="https://avatars.githubusercontent.com/u/14012511?v=4?s=100" width="100px;" alt="Lei Chen"/><br /><sub><b>Lei Chen</b></sub></a><br /><a href="https://github.com/The Less CSS Team/Less.js/commits?author=iChenLei" title="Code">💻</a> <a href="https://github.com/The Less CSS Team/Less.js/issues?q=author%3AiChenLei" title="Bug reports">🐛</a> <a href="https://github.com/The Less CSS Team/Less.js/commits?author=iChenLei" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/puckowski"><img src="https://avatars.githubusercontent.com/u/3059609?v=4?s=100" width="100px;" alt="Daniel Puckowski"/><br /><sub><b>Daniel Puckowski</b></sub></a><br /><a href="https://github.com/The Less CSS Team/Less.js/commits?author=puckowski" title="Code">💻</a> <a href="https://github.com/The Less CSS Team/Less.js/issues?q=author%3Apuckowski" title="Bug reports">🐛</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td align="center" size="13px" colspan="7">
|
||||
<img src="https://raw.githubusercontent.com/all-contributors/all-contributors-cli/1b8533af435da9854653492b1327a23a4dbd0a10/assets/logo-small.svg">
|
||||
<a href="https://all-contributors.js.org/docs/en/bot/usage">Add your contributions</a>
|
||||
</img>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
|
||||
## [License](LICENSE)
|
||||
|
||||
|
||||
225
dist/less.js
vendored
225
dist/less.js
vendored
@@ -962,47 +962,6 @@
|
||||
ALL: 2
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
var __assign = function() {
|
||||
__assign = Object.assign || function __assign(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
|
||||
function __spreadArray(to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
}
|
||||
|
||||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
||||
var e = new Error(message);
|
||||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the object type of the given payload
|
||||
*
|
||||
@@ -1034,7 +993,7 @@
|
||||
}
|
||||
|
||||
function assignProp(carry, key, newVal, originalObject, includeNonenumerable) {
|
||||
var propType = {}.propertyIsEnumerable.call(originalObject, key)
|
||||
const propType = {}.propertyIsEnumerable.call(originalObject, key)
|
||||
? 'enumerable'
|
||||
: 'nonenumerable';
|
||||
if (propType === 'enumerable')
|
||||
@@ -1058,22 +1017,21 @@
|
||||
* @returns {T} the target with replaced values
|
||||
* @export
|
||||
*/
|
||||
function copy(target, options) {
|
||||
if (options === void 0) { options = {}; }
|
||||
function copy(target, options = {}) {
|
||||
if (isArray(target)) {
|
||||
return target.map(function (item) { return copy(item, options); });
|
||||
return target.map((item) => copy(item, options));
|
||||
}
|
||||
if (!isPlainObject(target)) {
|
||||
return target;
|
||||
}
|
||||
var props = Object.getOwnPropertyNames(target);
|
||||
var symbols = Object.getOwnPropertySymbols(target);
|
||||
return __spreadArray(__spreadArray([], props, true), symbols, true).reduce(function (carry, key) {
|
||||
const props = Object.getOwnPropertyNames(target);
|
||||
const symbols = Object.getOwnPropertySymbols(target);
|
||||
return [...props, ...symbols].reduce((carry, key) => {
|
||||
if (isArray(options.props) && !options.props.includes(key)) {
|
||||
return carry;
|
||||
}
|
||||
var val = target[key];
|
||||
var newVal = copy(val, options);
|
||||
const val = target[key];
|
||||
const newVal = copy(val, options);
|
||||
assignProp(carry, key, newVal, target, options.nonenumerable);
|
||||
return carry;
|
||||
}, {});
|
||||
@@ -1299,20 +1257,24 @@
|
||||
* @returns {string}
|
||||
*/
|
||||
LessError.prototype.toString = function (options) {
|
||||
var _a;
|
||||
options = options || {};
|
||||
var isWarning = ((_a = this.type) !== null && _a !== void 0 ? _a : '').toLowerCase().includes('warning');
|
||||
var type = isWarning ? this.type : "".concat(this.type, "Error");
|
||||
var color = isWarning ? 'yellow' : 'red';
|
||||
var message = '';
|
||||
var extract = this.extract || [];
|
||||
var error = [];
|
||||
var stylize = function (str) { return str; };
|
||||
if (options.stylize) {
|
||||
var type = typeof options.stylize;
|
||||
if (type !== 'function') {
|
||||
throw Error("options.stylize should be a function, got a ".concat(type, "!"));
|
||||
var type_1 = typeof options.stylize;
|
||||
if (type_1 !== 'function') {
|
||||
throw Error("options.stylize should be a function, got a ".concat(type_1, "!"));
|
||||
}
|
||||
stylize = options.stylize;
|
||||
}
|
||||
if (this.line !== null) {
|
||||
if (typeof extract[0] === 'string') {
|
||||
if (!isWarning && typeof extract[0] === 'string') {
|
||||
error.push(stylize("".concat(this.line - 1, " ").concat(extract[0]), 'grey'));
|
||||
}
|
||||
if (typeof extract[1] === 'string') {
|
||||
@@ -1324,21 +1286,21 @@
|
||||
}
|
||||
error.push(errorTxt);
|
||||
}
|
||||
if (typeof extract[2] === 'string') {
|
||||
if (!isWarning && typeof extract[2] === 'string') {
|
||||
error.push(stylize("".concat(this.line + 1, " ").concat(extract[2]), 'grey'));
|
||||
}
|
||||
error = "".concat(error.join('\n') + stylize('', 'reset'), "\n");
|
||||
}
|
||||
message += stylize("".concat(this.type, "Error: ").concat(this.message), 'red');
|
||||
message += stylize("".concat(type, ": ").concat(this.message), color);
|
||||
if (this.filename) {
|
||||
message += stylize(' in ', 'red') + this.filename;
|
||||
message += stylize(' in ', color) + this.filename;
|
||||
}
|
||||
if (this.line) {
|
||||
message += stylize(" on line ".concat(this.line, ", column ").concat(this.column + 1, ":"), 'grey');
|
||||
}
|
||||
message += "\n".concat(error);
|
||||
if (this.callLine) {
|
||||
message += "".concat(stylize('from ', 'red') + (this.filename || ''), "/n");
|
||||
message += "".concat(stylize('from ', color) + (this.filename || ''), "/n");
|
||||
message += "".concat(stylize(this.callLine, 'grey'), " ").concat(this.callExtract, "/n");
|
||||
}
|
||||
return message;
|
||||
@@ -1519,7 +1481,8 @@
|
||||
// context
|
||||
'processImports',
|
||||
// Used by the import manager to stop multiple import visitors being created.
|
||||
'pluginManager' // Used as the plugin manager for the session
|
||||
'pluginManager',
|
||||
'quiet', // option - whether to log warnings
|
||||
];
|
||||
contexts.Parse = function (options) {
|
||||
copyFromOriginal(options, this, parseCopyProperties);
|
||||
@@ -2006,7 +1969,12 @@
|
||||
catch (_) { }
|
||||
if (!indices["".concat(extend.index, " ").concat(selector)]) {
|
||||
indices["".concat(extend.index, " ").concat(selector)] = true;
|
||||
logger$1.warn("extend '".concat(selector, "' has no matches"));
|
||||
/**
|
||||
* @todo Shouldn't this be an error? To alert the developer
|
||||
* that they may have made an error in the selector they are
|
||||
* targeting?
|
||||
*/
|
||||
logger$1.warn("WARNING: extend '".concat(selector, "' has no matches"));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -3310,6 +3278,22 @@
|
||||
message: msg
|
||||
}, imports);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {string} msg
|
||||
* @param {number} index
|
||||
* @param {string} type
|
||||
*/
|
||||
function warn(msg, index, type) {
|
||||
if (!context.quiet) {
|
||||
logger$1.warn((new LessError({
|
||||
index: index !== null && index !== void 0 ? index : parserInput.i,
|
||||
filename: fileInfo.filename,
|
||||
type: type ? "".concat(type.toUpperCase(), " WARNING") : 'WARNING',
|
||||
message: msg
|
||||
}, imports)).toString());
|
||||
}
|
||||
}
|
||||
function expect(arg, msg) {
|
||||
// some older browsers return typeof 'function' for RegExp
|
||||
var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
|
||||
@@ -4017,11 +4001,20 @@
|
||||
do {
|
||||
option = null;
|
||||
elements = null;
|
||||
var first = true;
|
||||
while (!(option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
|
||||
e = this.element();
|
||||
if (!e) {
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* @note - This will not catch selectors in pseudos like :is() and :where() because
|
||||
* they don't currently parse their contents as selectors.
|
||||
*/
|
||||
if (!first && e.combinator.value) {
|
||||
warn('Targeting complex selectors can have unexpected behavior, and this behavior may change in the future.', index);
|
||||
}
|
||||
first = false;
|
||||
if (elements) {
|
||||
elements.push(e);
|
||||
}
|
||||
@@ -4081,16 +4074,23 @@
|
||||
var elements;
|
||||
var args;
|
||||
var hasParens;
|
||||
var parensIndex;
|
||||
var parensWS = false;
|
||||
if (s !== '.' && s !== '#') {
|
||||
return;
|
||||
}
|
||||
parserInput.save(); // stop us absorbing part of an invalid selector
|
||||
elements = this.elements();
|
||||
if (elements) {
|
||||
parensIndex = parserInput.i;
|
||||
if (parserInput.$char('(')) {
|
||||
parensWS = parserInput.isWhitespace(-2);
|
||||
args = this.args(true).args;
|
||||
expectChar(')');
|
||||
hasParens = true;
|
||||
if (parensWS) {
|
||||
warn('Whitespace between a mixin name and parentheses for a mixin call is deprecated', parensIndex, 'DEPRECATED');
|
||||
}
|
||||
}
|
||||
if (getLookup !== false) {
|
||||
lookups = this.ruleLookups();
|
||||
@@ -4114,6 +4114,9 @@
|
||||
return new tree.NamespaceValue(mixin, lookups);
|
||||
}
|
||||
else {
|
||||
if (!hasParens) {
|
||||
warn('Calling a mixin without parentheses is deprecated', parensIndex, 'DEPRECATED');
|
||||
}
|
||||
return mixin;
|
||||
}
|
||||
}
|
||||
@@ -4403,24 +4406,25 @@
|
||||
expectChar(')');
|
||||
return new tree.Quoted('', "alpha(opacity=".concat(value, ")"));
|
||||
},
|
||||
//
|
||||
// A Selector Element
|
||||
//
|
||||
// div
|
||||
// + h1
|
||||
// #socks
|
||||
// input[type="text"]
|
||||
//
|
||||
// Elements are the building blocks for Selectors,
|
||||
// they are made out of a `Combinator` (see combinator rule),
|
||||
// and an element name, such as a tag a class, or `*`.
|
||||
//
|
||||
/**
|
||||
* A Selector Element
|
||||
*
|
||||
* div
|
||||
* + h1
|
||||
* #socks
|
||||
* input[type="text"]
|
||||
*
|
||||
* Elements are the building blocks for Selectors,
|
||||
* they are made out of a `Combinator` (see combinator rule),
|
||||
* and an element name, such as a tag a class, or `*`.
|
||||
*/
|
||||
element: function () {
|
||||
var e;
|
||||
var c;
|
||||
var v;
|
||||
var index = parserInput.i;
|
||||
c = this.combinator();
|
||||
/** This selector parser is quite simplistic and will pass a number of invalid selectors. */
|
||||
e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
|
||||
// eslint-disable-next-line no-control-regex
|
||||
parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
|
||||
@@ -5237,7 +5241,14 @@
|
||||
break;
|
||||
}
|
||||
parserInput.save();
|
||||
op = parserInput.$char('/') || parserInput.$char('*') || parserInput.$str('./');
|
||||
op = parserInput.$char('/') || parserInput.$char('*');
|
||||
if (!op) {
|
||||
var index = parserInput.i;
|
||||
op = parserInput.$str('./');
|
||||
if (op) {
|
||||
warn('./ operator is deprecated', index, 'DEPRECATED');
|
||||
}
|
||||
}
|
||||
if (!op) {
|
||||
parserInput.forget();
|
||||
break;
|
||||
@@ -7113,6 +7124,47 @@
|
||||
}
|
||||
});
|
||||
|
||||
/******************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
var __assign = function() {
|
||||
__assign = Object.assign || function __assign(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
|
||||
function __spreadArray(to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
}
|
||||
|
||||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
||||
var e = new Error(message);
|
||||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
||||
};
|
||||
|
||||
var Expression = function (value, noSpacing) {
|
||||
this.value = value;
|
||||
this.noSpacing = noSpacing;
|
||||
@@ -10855,19 +10907,22 @@
|
||||
var version = "4.2.2";
|
||||
|
||||
function parseNodeVersion(version) {
|
||||
var match = version.match(/^v(\d{1,2})\.(\d{1,2})\.(\d{1,2})(?:-([0-9A-Za-z-.]+))?(?:\+([0-9A-Za-z-.]+))?$/); // eslint-disable-line max-len
|
||||
if (!match) {
|
||||
throw new Error('Unable to parse: ' + version);
|
||||
}
|
||||
var res = {
|
||||
major: parseInt(match[1], 10),
|
||||
minor: parseInt(match[2], 10),
|
||||
patch: parseInt(match[3], 10),
|
||||
pre: match[4] || '',
|
||||
build: match[5] || '',
|
||||
};
|
||||
return res;
|
||||
var match = version.match(/^v(\d{1,2})\.(\d{1,2})\.(\d{1,2})(?:-([0-9A-Za-z-.]+))?(?:\+([0-9A-Za-z-.]+))?$/); // eslint-disable-line max-len
|
||||
if (!match) {
|
||||
throw new Error('Unable to parse: ' + version);
|
||||
}
|
||||
|
||||
var res = {
|
||||
major: parseInt(match[1], 10),
|
||||
minor: parseInt(match[2], 10),
|
||||
patch: parseInt(match[3], 10),
|
||||
pre: match[4] || '',
|
||||
build: match[5] || '',
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
var parseNodeVersion_1 = parseNodeVersion;
|
||||
|
||||
function lessRoot (environment, fileManagers) {
|
||||
|
||||
2
dist/less.min.js
vendored
2
dist/less.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/less.min.js.map
vendored
2
dist/less.min.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"useNx": false,
|
||||
"npmClient": "npm",
|
||||
"version": "4.2.2"
|
||||
}
|
||||
19651
package-lock.json
generated
19651
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,12 +8,9 @@
|
||||
"publish": "lerna publish from-package --no-private",
|
||||
"changelog": "github-changes -o less -r less.js -a --only-pulls --use-commit-body -m \"(YYYY-MM-DD)\"",
|
||||
"test": "cd packages/less && npm test",
|
||||
"postinstall": "lerna bootstrap"
|
||||
},
|
||||
"author": {
|
||||
"name": "Alexis Sellier",
|
||||
"email": "self@cloudhead.net"
|
||||
"postinstall": "npx only-allow pnpm"
|
||||
},
|
||||
"author": "Alexis Sellier <self@cloudhead.net>",
|
||||
"contributors": [
|
||||
"The Core Less Team"
|
||||
],
|
||||
@@ -26,6 +23,7 @@
|
||||
"url": "https://github.com/less/less.js.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"all-contributors-cli": "~6.26.1",
|
||||
"github-changes": "^1.1.2",
|
||||
"lerna": "^3.22.1",
|
||||
"npm-run-all": "^4.1.5"
|
||||
|
||||
@@ -197,8 +197,6 @@ module.exports = function(grunt) {
|
||||
command: [
|
||||
/** Browser runtime */
|
||||
"node build/rollup.js --dist",
|
||||
/** Copy to repo root */
|
||||
"npm run copy:root",
|
||||
/** Node.js runtime */
|
||||
"npm run build"
|
||||
].join(" && ")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* eslint indent: [2, 2, {"SwitchCase": 1}] */
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('../lib/less-node/fs').default;
|
||||
@@ -27,6 +27,7 @@ var plugins = [];
|
||||
var queuePlugins = [];
|
||||
var args = process.argv.slice(1);
|
||||
var silent = false;
|
||||
var quiet = false;
|
||||
var verbose = false;
|
||||
var options = less.options;
|
||||
options.plugins = plugins;
|
||||
@@ -36,7 +37,7 @@ var continueProcessing = true;
|
||||
|
||||
var checkArgFunc = function checkArgFunc(arg, option) {
|
||||
if (!option) {
|
||||
console.error("".concat(arg, " option requires a parameter"));
|
||||
console.error(''.concat(arg, ' option requires a parameter'));
|
||||
continueProcessing = false;
|
||||
process.exitCode = 1;
|
||||
return false;
|
||||
@@ -49,7 +50,7 @@ var checkBooleanArg = function checkBooleanArg(arg) {
|
||||
var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg);
|
||||
|
||||
if (!onOff) {
|
||||
console.error(" unable to parse ".concat(arg, " as a boolean. use one of on/t/true/y/yes/off/f/false/n/no"));
|
||||
console.error(' unable to parse '.concat(arg, ' as a boolean. use one of on/t/true/y/yes/off/f/false/n/no'));
|
||||
continueProcessing = false;
|
||||
process.exitCode = 1;
|
||||
return false;
|
||||
@@ -110,7 +111,7 @@ function render() {
|
||||
|
||||
if (output) {
|
||||
sourceMapOptions.sourceMapOutputFilename = path.basename(output);
|
||||
sourceMapOptions.sourceMapFullFilename = "".concat(output, ".map");
|
||||
sourceMapOptions.sourceMapFullFilename = ''.concat(output, '.map');
|
||||
} // its in the same directory, so always just the basename
|
||||
|
||||
|
||||
@@ -180,7 +181,7 @@ function render() {
|
||||
return;
|
||||
}
|
||||
|
||||
process.stdout.write("".concat(outputbase, ": "));
|
||||
process.stdout.write(''.concat(outputbase, ': '));
|
||||
}
|
||||
|
||||
if (!sourceMapFileInline) {
|
||||
@@ -200,14 +201,14 @@ function render() {
|
||||
if (errno && errno.errno[err.errno]) {
|
||||
description += errno.errno[err.errno].description;
|
||||
} else {
|
||||
description += "".concat(err.code, " ").concat(err.message);
|
||||
description += ''.concat(err.code, ' ').concat(err.message);
|
||||
}
|
||||
|
||||
console.error("lessc: failed to create file ".concat(filename));
|
||||
console.error('lessc: failed to create file '.concat(filename));
|
||||
console.error(description);
|
||||
process.exitCode = 1;
|
||||
} else {
|
||||
less.logger.info("lessc: wrote ".concat(filename));
|
||||
less.logger.info('lessc: wrote '.concat(filename));
|
||||
}
|
||||
|
||||
onDone();
|
||||
@@ -238,14 +239,14 @@ function render() {
|
||||
if (errno && errno.errno[err.errno]) {
|
||||
description += errno.errno[err.errno].description;
|
||||
} else {
|
||||
description += "".concat(err.code, " ").concat(err.message);
|
||||
description += ''.concat(err.code, ' ').concat(err.message);
|
||||
}
|
||||
|
||||
console.error("lessc: failed to create file ".concat(output));
|
||||
console.error('lessc: failed to create file '.concat(output));
|
||||
console.error(description);
|
||||
process.exitCode = 1;
|
||||
} else {
|
||||
less.logger.info("lessc: wrote ".concat(output));
|
||||
less.logger.info('lessc: wrote '.concat(output));
|
||||
|
||||
onSuccess();
|
||||
}
|
||||
@@ -261,7 +262,7 @@ function render() {
|
||||
var depends = '';
|
||||
|
||||
for (var i = 0; i < result.imports.length; i++) {
|
||||
depends += "".concat(result.imports[i], " ");
|
||||
depends += ''.concat(result.imports[i], ' ');
|
||||
}
|
||||
|
||||
console.log(depends);
|
||||
@@ -270,7 +271,7 @@ function render() {
|
||||
|
||||
var parseLessFile = function parseLessFile(e, data) {
|
||||
if (e) {
|
||||
console.error("lessc: ".concat(e.message));
|
||||
console.error('lessc: '.concat(e.message));
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
@@ -297,12 +298,14 @@ function render() {
|
||||
},
|
||||
warn: function warn(msg) {
|
||||
// do not show warning if the silent option is used
|
||||
if (!silent) {
|
||||
if (!silent && !quiet) {
|
||||
console.warn(msg);
|
||||
}
|
||||
},
|
||||
error: function error(msg) {
|
||||
console.error(msg);
|
||||
if (!silent) {
|
||||
console.error(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -344,7 +347,7 @@ function processPluginQueue() {
|
||||
var x = 0;
|
||||
|
||||
function pluginError(name) {
|
||||
console.error("Unable to load plugin ".concat(name, " please make sure that it is installed under or at the same level as less"));
|
||||
console.error('Unable to load plugin '.concat(name, ' please make sure that it is installed under or at the same level as less'));
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
@@ -393,17 +396,21 @@ function processPluginQueue() {
|
||||
switch (arg) {
|
||||
case 'v':
|
||||
case 'version':
|
||||
console.log("lessc ".concat(less.version.join('.'), " (Less Compiler) [JavaScript]"));
|
||||
console.log('lessc '.concat(less.version.join('.'), ' (Less Compiler) [JavaScript]'));
|
||||
continueProcessing = false;
|
||||
break;
|
||||
|
||||
case 'verbose':
|
||||
verbose = true;
|
||||
options.verbose = verbose = true;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
case 'silent':
|
||||
silent = true;
|
||||
options.silent = silent = true;
|
||||
break;
|
||||
|
||||
case 'quiet':
|
||||
options.quiet = quiet = true;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
@@ -552,7 +559,7 @@ function processPluginQueue() {
|
||||
} else if (m === 'all') {
|
||||
options.rewriteUrls = Constants.RewriteUrls.ALL;
|
||||
} else {
|
||||
console.error("Unknown rewrite-urls argument ".concat(m));
|
||||
console.error('Unknown rewrite-urls argument '.concat(m));
|
||||
continueProcessing = false;
|
||||
process.exitCode = 1;
|
||||
}
|
||||
@@ -575,8 +582,8 @@ function processPluginQueue() {
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
case 'math':
|
||||
var m = match[2];
|
||||
case 'math': {
|
||||
let m = match[2];
|
||||
if (checkArgFunc(arg, m)) {
|
||||
if (m === 'always') {
|
||||
console.warn('--math=always is deprecated and will be removed in the future.');
|
||||
@@ -592,7 +599,7 @@ function processPluginQueue() {
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
case 'su':
|
||||
case 'strict-units':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
|
||||
1
packages/less/dist
Symbolic link
1
packages/less/dist
Symbolic link
@@ -0,0 +1 @@
|
||||
../../dist
|
||||
11618
packages/less/dist/less.js
vendored
11618
packages/less/dist/less.js
vendored
File diff suppressed because it is too large
Load Diff
11
packages/less/dist/less.min.js
vendored
11
packages/less/dist/less.min.js
vendored
File diff suppressed because one or more lines are too long
1
packages/less/dist/less.min.js.map
vendored
1
packages/less/dist/less.min.js.map
vendored
File diff suppressed because one or more lines are too long
13786
packages/less/package-lock.json
generated
13786
packages/less/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"browser": "./dist/less.js",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"node": ">=14"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "grunt test",
|
||||
@@ -42,7 +42,6 @@
|
||||
"build": "npm-run-all clean compile",
|
||||
"clean": "shx rm -rf ./lib tsconfig.tsbuildinfo",
|
||||
"compile": "tsc -p tsconfig.build.json",
|
||||
"copy:root": "shx cp -rf ./dist ../../",
|
||||
"dev": "tsc -p tsconfig.build.json -w",
|
||||
"prepublishOnly": "grunt dist"
|
||||
},
|
||||
@@ -56,8 +55,8 @@
|
||||
"source-map": "~0.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@less/test-data": "^4.2.2",
|
||||
"@less/test-import-module": "^4.0.0",
|
||||
"@less/test-data": "workspace:*",
|
||||
"@less/test-import-module": "workspace:*",
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^11.0.0",
|
||||
|
||||
@@ -33,6 +33,7 @@ const lessc_helper = {
|
||||
console.log(' --js Enables inline JavaScript in less files');
|
||||
console.log(' -l, --lint Syntax check only (lint).');
|
||||
console.log(' -s, --silent Suppresses output of error messages.');
|
||||
console.log(' --quiet Suppresses output of warnings.');
|
||||
console.log(' --strict-imports Forces evaluation of imports.');
|
||||
console.log(' --insecure Allows imports from insecure https hosts.');
|
||||
console.log(' -v, --version Prints version number and exit.');
|
||||
|
||||
@@ -31,7 +31,8 @@ const parseCopyProperties = [
|
||||
// context
|
||||
'processImports', // option & context - whether to process imports. if false then imports will not be imported.
|
||||
// Used by the import manager to stop multiple import visitors being created.
|
||||
'pluginManager' // Used as the plugin manager for the session
|
||||
'pluginManager', // Used as the plugin manager for the session
|
||||
'quiet', // option - whether to log warnings
|
||||
];
|
||||
|
||||
contexts.Parse = function(options) {
|
||||
|
||||
@@ -106,6 +106,9 @@ LessError.prototype.constructor = LessError;
|
||||
*/
|
||||
LessError.prototype.toString = function(options) {
|
||||
options = options || {};
|
||||
const isWarning = (this.type ?? '').toLowerCase().includes('warning');
|
||||
const type = isWarning ? this.type : `${this.type}Error`;
|
||||
const color = isWarning ? 'yellow' : 'red';
|
||||
|
||||
let message = '';
|
||||
const extract = this.extract || [];
|
||||
@@ -120,7 +123,7 @@ LessError.prototype.toString = function(options) {
|
||||
}
|
||||
|
||||
if (this.line !== null) {
|
||||
if (typeof extract[0] === 'string') {
|
||||
if (!isWarning && typeof extract[0] === 'string') {
|
||||
error.push(stylize(`${this.line - 1} ${extract[0]}`, 'grey'));
|
||||
}
|
||||
|
||||
@@ -134,15 +137,15 @@ LessError.prototype.toString = function(options) {
|
||||
error.push(errorTxt);
|
||||
}
|
||||
|
||||
if (typeof extract[2] === 'string') {
|
||||
if (!isWarning && typeof extract[2] === 'string') {
|
||||
error.push(stylize(`${this.line + 1} ${extract[2]}`, 'grey'));
|
||||
}
|
||||
error = `${error.join('\n') + stylize('', 'reset')}\n`;
|
||||
}
|
||||
|
||||
message += stylize(`${this.type}Error: ${this.message}`, 'red');
|
||||
message += stylize(`${type}: ${this.message}`, color);
|
||||
if (this.filename) {
|
||||
message += stylize(' in ', 'red') + this.filename;
|
||||
message += stylize(' in ', color) + this.filename;
|
||||
}
|
||||
if (this.line) {
|
||||
message += stylize(` on line ${this.line}, column ${this.column + 1}:`, 'grey');
|
||||
@@ -151,7 +154,7 @@ LessError.prototype.toString = function(options) {
|
||||
message += `\n${error}`;
|
||||
|
||||
if (this.callLine) {
|
||||
message += `${stylize('from ', 'red') + (this.filename || '')}/n`;
|
||||
message += `${stylize('from ', color) + (this.filename || '')}/n`;
|
||||
message += `${stylize(this.callLine, 'grey')} ${this.callExtract}/n`;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import getParserInput from './parser-input';
|
||||
import * as utils from '../utils';
|
||||
import functionRegistry from '../functions/function-registry';
|
||||
import { ContainerSyntaxOptions, MediaSyntaxOptions } from '../tree/atrule-syntax';
|
||||
import logger from '../logger';
|
||||
import Selector from '../tree/selector';
|
||||
import Anonymous from '../tree/anonymous';
|
||||
|
||||
@@ -58,6 +59,28 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} msg
|
||||
* @param {number} index
|
||||
* @param {string} type
|
||||
*/
|
||||
function warn(msg, index, type) {
|
||||
if (!context.quiet) {
|
||||
logger.warn(
|
||||
(new LessError(
|
||||
{
|
||||
index: index ?? parserInput.i,
|
||||
filename: fileInfo.filename,
|
||||
type: type ? `${type.toUpperCase()} WARNING` : 'WARNING',
|
||||
message: msg
|
||||
},
|
||||
imports
|
||||
)).toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function expect(arg, msg) {
|
||||
// some older browsers return typeof 'function' for RegExp
|
||||
const result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
|
||||
@@ -858,11 +881,22 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
do {
|
||||
option = null;
|
||||
elements = null;
|
||||
while (!(option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
|
||||
let first = true;
|
||||
while (!(option = parserInput.$re(/^(!?all)(?=\s*(\)|,))/))) {
|
||||
e = this.element();
|
||||
|
||||
if (!e) {
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* @note - This will not catch selectors in pseudos like :is() and :where() because
|
||||
* they don't currently parse their contents as selectors.
|
||||
*/
|
||||
if (!first && e.combinator.value) {
|
||||
warn('Targeting complex selectors can have unexpected behavior, and this behavior may change in the future.', index)
|
||||
}
|
||||
|
||||
first = false;
|
||||
if (elements) {
|
||||
elements.push(e);
|
||||
} else {
|
||||
@@ -926,6 +960,8 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
let elements;
|
||||
let args;
|
||||
let hasParens;
|
||||
let parensIndex;
|
||||
let parensWS = false;
|
||||
|
||||
if (s !== '.' && s !== '#') { return; }
|
||||
|
||||
@@ -934,10 +970,15 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
elements = this.elements();
|
||||
|
||||
if (elements) {
|
||||
parensIndex = parserInput.i;
|
||||
if (parserInput.$char('(')) {
|
||||
parensWS = parserInput.isWhitespace(-2);
|
||||
args = this.args(true).args;
|
||||
expectChar(')');
|
||||
hasParens = true;
|
||||
if (parensWS) {
|
||||
warn('Whitespace between a mixin name and parentheses for a mixin call is deprecated', parensIndex, 'DEPRECATED');
|
||||
}
|
||||
}
|
||||
|
||||
if (getLookup !== false) {
|
||||
@@ -965,6 +1006,9 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
return new tree.NamespaceValue(mixin, lookups);
|
||||
}
|
||||
else {
|
||||
if (!hasParens) {
|
||||
warn('Calling a mixin without parentheses is deprecated', parensIndex, 'DEPRECATED');
|
||||
}
|
||||
return mixin;
|
||||
}
|
||||
}
|
||||
@@ -1284,18 +1328,18 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
return new tree.Quoted('', `alpha(opacity=${value})`);
|
||||
},
|
||||
|
||||
//
|
||||
// A Selector Element
|
||||
//
|
||||
// div
|
||||
// + h1
|
||||
// #socks
|
||||
// input[type="text"]
|
||||
//
|
||||
// Elements are the building blocks for Selectors,
|
||||
// they are made out of a `Combinator` (see combinator rule),
|
||||
// and an element name, such as a tag a class, or `*`.
|
||||
//
|
||||
/**
|
||||
* A Selector Element
|
||||
*
|
||||
* div
|
||||
* + h1
|
||||
* #socks
|
||||
* input[type="text"]
|
||||
*
|
||||
* Elements are the building blocks for Selectors,
|
||||
* they are made out of a `Combinator` (see combinator rule),
|
||||
* and an element name, such as a tag a class, or `*`.
|
||||
*/
|
||||
element: function () {
|
||||
let e;
|
||||
let c;
|
||||
@@ -1304,6 +1348,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
|
||||
c = this.combinator();
|
||||
|
||||
/** This selector parser is quite simplistic and will pass a number of invalid selectors. */
|
||||
e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
|
||||
// eslint-disable-next-line no-control-regex
|
||||
parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
|
||||
@@ -1601,7 +1646,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
if (parserInput.$char(';')) {
|
||||
value = new Anonymous('');
|
||||
} else {
|
||||
value = this.permissiveValue(/[;}]/);
|
||||
value = this.permissiveValue(/[;}]/, true);
|
||||
}
|
||||
}
|
||||
// Try to store values as anonymous
|
||||
@@ -1622,7 +1667,12 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
if (value) {
|
||||
important = this.important();
|
||||
} else if (isVariable) {
|
||||
// As a last resort, try permissiveValue
|
||||
/**
|
||||
* As a last resort, try permissiveValue
|
||||
*
|
||||
* @todo - This has created some knock-on problems of not
|
||||
* flagging incorrect syntax or detecting user intent.
|
||||
*/
|
||||
value = this.permissiveValue();
|
||||
}
|
||||
}
|
||||
@@ -1653,6 +1703,8 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
* First, it will try to parse comments and entities to reach
|
||||
* the end. This is mostly like the Expression parser except no
|
||||
* math is allowed.
|
||||
*
|
||||
* @param {RexExp} untilTokens - Characters to stop parsing at
|
||||
*/
|
||||
permissiveValue: function (untilTokens) {
|
||||
let i;
|
||||
@@ -1718,6 +1770,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
parserInput.forget();
|
||||
return new tree.Anonymous('', index);
|
||||
}
|
||||
/** @type {string} */
|
||||
let item;
|
||||
for (i = 0; i < value.length; i++) {
|
||||
item = value[i];
|
||||
@@ -1731,10 +1784,16 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
}
|
||||
// Treat like quoted values, but replace vars like unquoted expressions
|
||||
const quote = new tree.Quoted('\'', item, true, index, fileInfo);
|
||||
if (!item.startsWith('@{')) {
|
||||
quote.variableRegex = /@([\w-]+)/g;
|
||||
const variableRegex = /@([\w-]+)/g;
|
||||
const propRegex = /\$([\w-]+)/g;
|
||||
if (variableRegex.test(item)) {
|
||||
warn('@[ident] in unknown values will not be evaluated as variables in the future. Use @{[ident]}', index, 'DEPRECATED');
|
||||
}
|
||||
quote.propRegex = /\$([\w-]+)/g;
|
||||
if (propRegex.test(item)) {
|
||||
warn('$[ident] in unknown values will not be evaluated as property references in the future. Use ${[ident]}', index, 'DEPRECATED');
|
||||
}
|
||||
quote.variableRegex = /@([\w-]+)|@{([\w-]+)}/g;
|
||||
quote.propRegex = /\$([\w-]+)|\${([\w-]+)}/g;
|
||||
result.push(quote);
|
||||
}
|
||||
}
|
||||
@@ -2152,7 +2211,14 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
|
||||
|
||||
parserInput.save();
|
||||
|
||||
op = parserInput.$char('/') || parserInput.$char('*') || parserInput.$str('./');
|
||||
op = parserInput.$char('/') || parserInput.$char('*');
|
||||
if (!op) {
|
||||
let index = parserInput.i;
|
||||
op = parserInput.$str('./');
|
||||
if (op) {
|
||||
warn('./ operator is deprecated', index, 'DEPRECATED');
|
||||
}
|
||||
}
|
||||
|
||||
if (!op) { parserInput.forget(); break; }
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ const Extend = function(selector, option, index, currentFileInfo, visibilityInfo
|
||||
this.allowRoot = true;
|
||||
|
||||
switch (option) {
|
||||
case '!all':
|
||||
case 'all':
|
||||
this.allowBefore = true;
|
||||
this.allowAfter = true;
|
||||
|
||||
@@ -33,12 +33,12 @@ Quoted.prototype = Object.assign(new Node(), {
|
||||
eval(context) {
|
||||
const that = this;
|
||||
let value = this.value;
|
||||
const variableReplacement = function (_, name) {
|
||||
const v = new Variable(`@${name}`, that.getIndex(), that.fileInfo()).eval(context, true);
|
||||
const variableReplacement = function (_, name1, name2) {
|
||||
const v = new Variable(`@${name1 ?? name2}`, that.getIndex(), that.fileInfo()).eval(context, true);
|
||||
return (v instanceof Quoted) ? v.value : v.toCSS();
|
||||
};
|
||||
const propertyReplacement = function (_, name) {
|
||||
const v = new Property(`$${name}`, that.getIndex(), that.fileInfo()).eval(context, true);
|
||||
const propertyReplacement = function (_, name1, name2) {
|
||||
const v = new Property(`$${name1 ?? name2}`, that.getIndex(), that.fileInfo()).eval(context, true);
|
||||
return (v instanceof Quoted) ? v.value : v.toCSS();
|
||||
};
|
||||
function iterativeReplace(value, regexp, replacementFnc) {
|
||||
|
||||
@@ -133,7 +133,12 @@ class ProcessExtendsVisitor {
|
||||
|
||||
if (!indices[`${extend.index} ${selector}`]) {
|
||||
indices[`${extend.index} ${selector}`] = true;
|
||||
logger.warn(`extend '${selector}' has no matches`);
|
||||
/**
|
||||
* @todo Shouldn't this be an error? To alert the developer
|
||||
* that they may have made an error in the selector they are
|
||||
* targeting?
|
||||
*/
|
||||
logger.warn(`WARNING: extend '${selector}' has no matches`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ logger.addListener({
|
||||
warn(msg) {
|
||||
process.stdout.write(msg + '\n');
|
||||
},
|
||||
erro(msg) {
|
||||
error(msg) {
|
||||
process.stdout.write(msg + '\n');
|
||||
}
|
||||
});
|
||||
@@ -366,6 +366,8 @@ module.exports = function() {
|
||||
|
||||
var options = clone(originalOptions);
|
||||
|
||||
options.stylize = stylize;
|
||||
|
||||
var name = getBasename(file);
|
||||
|
||||
if (oneTestOnly && name !== oneTestOnly) {
|
||||
|
||||
@@ -31,6 +31,11 @@ foo[attr="blah"] {
|
||||
this: works;
|
||||
}
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.with-curly {
|
||||
this: works;
|
||||
}
|
||||
}
|
||||
.test-rule-comment {
|
||||
--value: a /* { ; } */;
|
||||
--comment-within: ( /* okay?; comment; */ );
|
||||
|
||||
@@ -59,7 +59,7 @@ div.ext5,
|
||||
}
|
||||
}
|
||||
|
||||
.fuu:extend(.ext8.ext9 all) {}
|
||||
.fuu:extend( .ext8.ext9 all) {}
|
||||
.buu:extend(.ext8 .ext9 all) {}
|
||||
.zap:extend(.ext8 + .ext9 all) {}
|
||||
.zoo:extend(.ext8 > .ext9 all) {}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#container {
|
||||
color: black;
|
||||
.mixin();
|
||||
.mixout();
|
||||
.mixout ();
|
||||
#theme > .mixin();
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
this: works;
|
||||
}
|
||||
}
|
||||
@tablet: (min-width: @{size});
|
||||
@media @tablet {
|
||||
.with-curly {
|
||||
this: works;
|
||||
}
|
||||
}
|
||||
// @todo - fix comment absorption after property
|
||||
.test-rule-comment {
|
||||
--value: a/* { ; } */;
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
},
|
||||
"version": "4.2.2",
|
||||
"description": "Less files and CSS results",
|
||||
"author": {
|
||||
"name": "Alexis Sellier",
|
||||
"email": "self@cloudhead.net"
|
||||
},
|
||||
"author": "Alexis Sellier <self@cloudhead.net>",
|
||||
"contributors": [
|
||||
"The Core Less Team"
|
||||
],
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
"private": true,
|
||||
"version": "4.0.0",
|
||||
"description": "Less files to be included in node_modules directory for testing import from node_modules",
|
||||
"author": {
|
||||
"name": "Alexis Sellier",
|
||||
"email": "self@cloudhead.net"
|
||||
},
|
||||
"author": "Alexis Sellier <self@cloudhead.net>",
|
||||
"contributors": [
|
||||
"The Core Less Team"
|
||||
],
|
||||
|
||||
9398
pnpm-lock.yaml
generated
Normal file
9398
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- 'packages/*'
|
||||
Reference in New Issue
Block a user