removed node_modules
This commit is contained in:
parent
e87ae9d160
commit
704079060f
|
@ -0,0 +1,10 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
quote_type = single
|
21
.eslintrc.js
21
.eslintrc.js
|
@ -1,21 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
plugins: [ '@typescript-eslint' ],
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/triple-slash-reference': 0,
|
|
||||||
'@typescript-eslint/no-unused-vars': 0,
|
|
||||||
'@typescript-eslint/no-explicit-any': 0,
|
|
||||||
'@typescript-eslint/ban-ts-comment': 0,
|
|
||||||
'@typescript-eslint/explicit-function-return-type': 1,
|
|
||||||
'quotes': [2, 'single', {avoidEscape: true},],
|
|
||||||
'no-extra-parens': 1,
|
|
||||||
'consistent-return': 1,
|
|
||||||
'no-eq-null': 1,
|
|
||||||
'no-implicit-globals': 1
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"plugins": ["@typescript-eslint"]
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
../acorn/bin/acorn
|
|
|
@ -1 +0,0 @@
|
||||||
../eslint/bin/eslint.js
|
|
|
@ -1 +0,0 @@
|
||||||
../esprima/bin/esparse.js
|
|
|
@ -1 +0,0 @@
|
||||||
../esprima/bin/esvalidate.js
|
|
|
@ -1 +0,0 @@
|
||||||
../js-yaml/bin/js-yaml.js
|
|
|
@ -1 +0,0 @@
|
||||||
../which/bin/node-which
|
|
|
@ -1 +0,0 @@
|
||||||
../rimraf/bin.js
|
|
|
@ -1 +0,0 @@
|
||||||
../semver/bin/semver.js
|
|
|
@ -1 +0,0 @@
|
||||||
../typescript/bin/tsc
|
|
|
@ -1 +0,0 @@
|
||||||
../typescript/bin/tsserver
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,19 +0,0 @@
|
||||||
# @babel/code-frame
|
|
||||||
|
|
||||||
> Generate errors that contain a code frame that point to source locations.
|
|
||||||
|
|
||||||
See our website [@babel/code-frame](https://babeljs.io/docs/en/babel-code-frame) for more information.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
Using npm:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install --save-dev @babel/code-frame
|
|
||||||
```
|
|
||||||
|
|
||||||
or using yarn:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add @babel/code-frame --dev
|
|
||||||
```
|
|
|
@ -1,167 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.codeFrameColumns = codeFrameColumns;
|
|
||||||
exports.default = _default;
|
|
||||||
|
|
||||||
var _highlight = _interopRequireWildcard(require("@babel/highlight"));
|
|
||||||
|
|
||||||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
||||||
|
|
||||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
||||||
|
|
||||||
let deprecationWarningShown = false;
|
|
||||||
|
|
||||||
function getDefs(chalk) {
|
|
||||||
return {
|
|
||||||
gutter: chalk.grey,
|
|
||||||
marker: chalk.red.bold,
|
|
||||||
message: chalk.red.bold
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
|
||||||
|
|
||||||
function getMarkerLines(loc, source, opts) {
|
|
||||||
const startLoc = Object.assign({
|
|
||||||
column: 0,
|
|
||||||
line: -1
|
|
||||||
}, loc.start);
|
|
||||||
const endLoc = Object.assign({}, startLoc, loc.end);
|
|
||||||
const {
|
|
||||||
linesAbove = 2,
|
|
||||||
linesBelow = 3
|
|
||||||
} = opts || {};
|
|
||||||
const startLine = startLoc.line;
|
|
||||||
const startColumn = startLoc.column;
|
|
||||||
const endLine = endLoc.line;
|
|
||||||
const endColumn = endLoc.column;
|
|
||||||
let start = Math.max(startLine - (linesAbove + 1), 0);
|
|
||||||
let end = Math.min(source.length, endLine + linesBelow);
|
|
||||||
|
|
||||||
if (startLine === -1) {
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endLine === -1) {
|
|
||||||
end = source.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lineDiff = endLine - startLine;
|
|
||||||
const markerLines = {};
|
|
||||||
|
|
||||||
if (lineDiff) {
|
|
||||||
for (let i = 0; i <= lineDiff; i++) {
|
|
||||||
const lineNumber = i + startLine;
|
|
||||||
|
|
||||||
if (!startColumn) {
|
|
||||||
markerLines[lineNumber] = true;
|
|
||||||
} else if (i === 0) {
|
|
||||||
const sourceLength = source[lineNumber - 1].length;
|
|
||||||
markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];
|
|
||||||
} else if (i === lineDiff) {
|
|
||||||
markerLines[lineNumber] = [0, endColumn];
|
|
||||||
} else {
|
|
||||||
const sourceLength = source[lineNumber - i].length;
|
|
||||||
markerLines[lineNumber] = [0, sourceLength];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (startColumn === endColumn) {
|
|
||||||
if (startColumn) {
|
|
||||||
markerLines[startLine] = [startColumn, 0];
|
|
||||||
} else {
|
|
||||||
markerLines[startLine] = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
markerLines[startLine] = [startColumn, endColumn - startColumn];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
markerLines
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function codeFrameColumns(rawLines, loc, opts = {}) {
|
|
||||||
const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight.shouldHighlight)(opts);
|
|
||||||
const chalk = (0, _highlight.getChalk)(opts);
|
|
||||||
const defs = getDefs(chalk);
|
|
||||||
|
|
||||||
const maybeHighlight = (chalkFn, string) => {
|
|
||||||
return highlighted ? chalkFn(string) : string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const lines = rawLines.split(NEWLINE);
|
|
||||||
const {
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
markerLines
|
|
||||||
} = getMarkerLines(loc, lines, opts);
|
|
||||||
const hasColumns = loc.start && typeof loc.start.column === "number";
|
|
||||||
const numberMaxWidth = String(end).length;
|
|
||||||
const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines;
|
|
||||||
let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => {
|
|
||||||
const number = start + 1 + index;
|
|
||||||
const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
|
|
||||||
const gutter = ` ${paddedNumber} | `;
|
|
||||||
const hasMarker = markerLines[number];
|
|
||||||
const lastMarkerLine = !markerLines[number + 1];
|
|
||||||
|
|
||||||
if (hasMarker) {
|
|
||||||
let markerLine = "";
|
|
||||||
|
|
||||||
if (Array.isArray(hasMarker)) {
|
|
||||||
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
|
|
||||||
const numberOfMarkers = hasMarker[1] || 1;
|
|
||||||
markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), markerSpacing, maybeHighlight(defs.marker, "^").repeat(numberOfMarkers)].join("");
|
|
||||||
|
|
||||||
if (lastMarkerLine && opts.message) {
|
|
||||||
markerLine += " " + maybeHighlight(defs.message, opts.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line, markerLine].join("");
|
|
||||||
} else {
|
|
||||||
return ` ${maybeHighlight(defs.gutter, gutter)}${line}`;
|
|
||||||
}
|
|
||||||
}).join("\n");
|
|
||||||
|
|
||||||
if (opts.message && !hasColumns) {
|
|
||||||
frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (highlighted) {
|
|
||||||
return chalk.reset(frame);
|
|
||||||
} else {
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _default(rawLines, lineNumber, colNumber, opts = {}) {
|
|
||||||
if (!deprecationWarningShown) {
|
|
||||||
deprecationWarningShown = true;
|
|
||||||
const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
|
|
||||||
|
|
||||||
if (process.emitWarning) {
|
|
||||||
process.emitWarning(message, "DeprecationWarning");
|
|
||||||
} else {
|
|
||||||
const deprecationError = new Error(message);
|
|
||||||
deprecationError.name = "DeprecationWarning";
|
|
||||||
console.warn(new Error(message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
colNumber = Math.max(colNumber, 0);
|
|
||||||
const location = {
|
|
||||||
start: {
|
|
||||||
column: colNumber,
|
|
||||||
line: lineNumber
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return codeFrameColumns(rawLines, location, opts);
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@babel/code-frame",
|
|
||||||
"version": "7.12.11",
|
|
||||||
"description": "Generate errors that contain a code frame that point to source locations.",
|
|
||||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
|
||||||
"homepage": "https://babeljs.io/",
|
|
||||||
"license": "MIT",
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/babel/babel.git",
|
|
||||||
"directory": "packages/babel-code-frame"
|
|
||||||
},
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/highlight": "^7.10.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/chalk": "^2.0.0",
|
|
||||||
"chalk": "^2.0.0",
|
|
||||||
"strip-ansi": "^4.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,19 +0,0 @@
|
||||||
# @babel/helper-validator-identifier
|
|
||||||
|
|
||||||
> Validate identifier/keywords name
|
|
||||||
|
|
||||||
See our website [@babel/helper-validator-identifier](https://babeljs.io/docs/en/babel-helper-validator-identifier) for more information.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
Using npm:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install --save-dev @babel/helper-validator-identifier
|
|
||||||
```
|
|
||||||
|
|
||||||
or using yarn:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add @babel/helper-validator-identifier --dev
|
|
||||||
```
|
|
|
@ -1,84 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.isIdentifierStart = isIdentifierStart;
|
|
||||||
exports.isIdentifierChar = isIdentifierChar;
|
|
||||||
exports.isIdentifierName = isIdentifierName;
|
|
||||||
let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
|
|
||||||
let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
|
|
||||||
const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
|
|
||||||
const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
|
||||||
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
|
|
||||||
const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 107, 20, 28, 22, 13, 52, 76, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 230, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 35, 56, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8952, 286, 50, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 2357, 44, 11, 6, 17, 0, 370, 43, 1301, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42717, 35, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938];
|
|
||||||
const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 135, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 419, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];
|
|
||||||
|
|
||||||
function isInAstralSet(code, set) {
|
|
||||||
let pos = 0x10000;
|
|
||||||
|
|
||||||
for (let i = 0, length = set.length; i < length; i += 2) {
|
|
||||||
pos += set[i];
|
|
||||||
if (pos > code) return false;
|
|
||||||
pos += set[i + 1];
|
|
||||||
if (pos >= code) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isIdentifierStart(code) {
|
|
||||||
if (code < 65) return code === 36;
|
|
||||||
if (code <= 90) return true;
|
|
||||||
if (code < 97) return code === 95;
|
|
||||||
if (code <= 122) return true;
|
|
||||||
|
|
||||||
if (code <= 0xffff) {
|
|
||||||
return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
|
|
||||||
}
|
|
||||||
|
|
||||||
return isInAstralSet(code, astralIdentifierStartCodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isIdentifierChar(code) {
|
|
||||||
if (code < 48) return code === 36;
|
|
||||||
if (code < 58) return true;
|
|
||||||
if (code < 65) return false;
|
|
||||||
if (code <= 90) return true;
|
|
||||||
if (code < 97) return code === 95;
|
|
||||||
if (code <= 122) return true;
|
|
||||||
|
|
||||||
if (code <= 0xffff) {
|
|
||||||
return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
|
|
||||||
}
|
|
||||||
|
|
||||||
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isIdentifierName(name) {
|
|
||||||
let isFirst = true;
|
|
||||||
|
|
||||||
for (let i = 0; i < name.length; i++) {
|
|
||||||
let cp = name.charCodeAt(i);
|
|
||||||
|
|
||||||
if ((cp & 0xfc00) === 0xd800 && i + 1 < name.length) {
|
|
||||||
const trail = name.charCodeAt(++i);
|
|
||||||
|
|
||||||
if ((trail & 0xfc00) === 0xdc00) {
|
|
||||||
cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFirst) {
|
|
||||||
isFirst = false;
|
|
||||||
|
|
||||||
if (!isIdentifierStart(cp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!isIdentifierChar(cp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !isFirst;
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isIdentifierName", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _identifier.isIdentifierName;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isIdentifierChar", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _identifier.isIdentifierChar;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isIdentifierStart", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _identifier.isIdentifierStart;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isReservedWord", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _keyword.isReservedWord;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isStrictBindOnlyReservedWord", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _keyword.isStrictBindOnlyReservedWord;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isStrictBindReservedWord", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _keyword.isStrictBindReservedWord;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isStrictReservedWord", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _keyword.isStrictReservedWord;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "isKeyword", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function () {
|
|
||||||
return _keyword.isKeyword;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var _identifier = require("./identifier");
|
|
||||||
|
|
||||||
var _keyword = require("./keyword");
|
|
|
@ -1,38 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.isReservedWord = isReservedWord;
|
|
||||||
exports.isStrictReservedWord = isStrictReservedWord;
|
|
||||||
exports.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord;
|
|
||||||
exports.isStrictBindReservedWord = isStrictBindReservedWord;
|
|
||||||
exports.isKeyword = isKeyword;
|
|
||||||
const reservedWords = {
|
|
||||||
keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"],
|
|
||||||
strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"],
|
|
||||||
strictBind: ["eval", "arguments"]
|
|
||||||
};
|
|
||||||
const keywords = new Set(reservedWords.keyword);
|
|
||||||
const reservedWordsStrictSet = new Set(reservedWords.strict);
|
|
||||||
const reservedWordsStrictBindSet = new Set(reservedWords.strictBind);
|
|
||||||
|
|
||||||
function isReservedWord(word, inModule) {
|
|
||||||
return inModule && word === "await" || word === "enum";
|
|
||||||
}
|
|
||||||
|
|
||||||
function isStrictReservedWord(word, inModule) {
|
|
||||||
return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isStrictBindOnlyReservedWord(word) {
|
|
||||||
return reservedWordsStrictBindSet.has(word);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isStrictBindReservedWord(word, inModule) {
|
|
||||||
return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isKeyword(word) {
|
|
||||||
return keywords.has(word);
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@babel/helper-validator-identifier",
|
|
||||||
"version": "7.14.9",
|
|
||||||
"description": "Validate identifier/keywords name",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/babel/babel.git",
|
|
||||||
"directory": "packages/babel-helper-validator-identifier"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"main": "./lib/index.js",
|
|
||||||
"exports": "./lib/index.js",
|
|
||||||
"devDependencies": {
|
|
||||||
"@unicode/unicode-13.0.0": "^1.0.6",
|
|
||||||
"charcodes": "^0.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
},
|
|
||||||
"author": "The Babel Team (https://babel.dev/team)"
|
|
||||||
}
|
|
75
node_modules/@babel/helper-validator-identifier/scripts/generate-identifier-regex.js
generated
vendored
75
node_modules/@babel/helper-validator-identifier/scripts/generate-identifier-regex.js
generated
vendored
|
@ -1,75 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Always use the latest available version of Unicode!
|
|
||||||
// https://tc39.github.io/ecma262/#sec-conformance
|
|
||||||
const version = "13.0.0";
|
|
||||||
|
|
||||||
const start = require("@unicode/unicode-" +
|
|
||||||
version +
|
|
||||||
"/Binary_Property/ID_Start/code-points.js").filter(function (ch) {
|
|
||||||
return ch > 0x7f;
|
|
||||||
});
|
|
||||||
let last = -1;
|
|
||||||
const cont = [0x200c, 0x200d].concat(
|
|
||||||
require("@unicode/unicode-" +
|
|
||||||
version +
|
|
||||||
"/Binary_Property/ID_Continue/code-points.js").filter(function (ch) {
|
|
||||||
return ch > 0x7f && search(start, ch, last + 1) == -1;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
function search(arr, ch, starting) {
|
|
||||||
for (let i = starting; arr[i] <= ch && i < arr.length; last = i++) {
|
|
||||||
if (arr[i] === ch) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pad(str, width) {
|
|
||||||
while (str.length < width) str = "0" + str;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function esc(code) {
|
|
||||||
const hex = code.toString(16);
|
|
||||||
if (hex.length <= 2) return "\\x" + pad(hex, 2);
|
|
||||||
else return "\\u" + pad(hex, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
function generate(chars) {
|
|
||||||
const astral = [];
|
|
||||||
let re = "";
|
|
||||||
for (let i = 0, at = 0x10000; i < chars.length; i++) {
|
|
||||||
const from = chars[i];
|
|
||||||
let to = from;
|
|
||||||
while (i < chars.length - 1 && chars[i + 1] == to + 1) {
|
|
||||||
i++;
|
|
||||||
to++;
|
|
||||||
}
|
|
||||||
if (to <= 0xffff) {
|
|
||||||
if (from == to) re += esc(from);
|
|
||||||
else if (from + 1 == to) re += esc(from) + esc(to);
|
|
||||||
else re += esc(from) + "-" + esc(to);
|
|
||||||
} else {
|
|
||||||
astral.push(from - at, to - from);
|
|
||||||
at = to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { nonASCII: re, astral: astral };
|
|
||||||
}
|
|
||||||
|
|
||||||
const startData = generate(start);
|
|
||||||
const contData = generate(cont);
|
|
||||||
|
|
||||||
console.log("/* prettier-ignore */");
|
|
||||||
console.log('let nonASCIIidentifierStartChars = "' + startData.nonASCII + '";');
|
|
||||||
console.log("/* prettier-ignore */");
|
|
||||||
console.log('let nonASCIIidentifierChars = "' + contData.nonASCII + '";');
|
|
||||||
console.log("/* prettier-ignore */");
|
|
||||||
console.log(
|
|
||||||
"const astralIdentifierStartCodes = " + JSON.stringify(startData.astral) + ";"
|
|
||||||
);
|
|
||||||
console.log("/* prettier-ignore */");
|
|
||||||
console.log(
|
|
||||||
"const astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";"
|
|
||||||
);
|
|
|
@ -1,22 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,19 +0,0 @@
|
||||||
# @babel/highlight
|
|
||||||
|
|
||||||
> Syntax highlight JavaScript strings for output in terminals.
|
|
||||||
|
|
||||||
See our website [@babel/highlight](https://babeljs.io/docs/en/babel-highlight) for more information.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
Using npm:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install --save-dev @babel/highlight
|
|
||||||
```
|
|
||||||
|
|
||||||
or using yarn:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn add @babel/highlight --dev
|
|
||||||
```
|
|
|
@ -1,116 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.shouldHighlight = shouldHighlight;
|
|
||||||
exports.getChalk = getChalk;
|
|
||||||
exports.default = highlight;
|
|
||||||
|
|
||||||
var _jsTokens = require("js-tokens");
|
|
||||||
|
|
||||||
var _helperValidatorIdentifier = require("@babel/helper-validator-identifier");
|
|
||||||
|
|
||||||
var _chalk = require("chalk");
|
|
||||||
|
|
||||||
const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]);
|
|
||||||
|
|
||||||
function getDefs(chalk) {
|
|
||||||
return {
|
|
||||||
keyword: chalk.cyan,
|
|
||||||
capitalized: chalk.yellow,
|
|
||||||
jsxIdentifier: chalk.yellow,
|
|
||||||
punctuator: chalk.yellow,
|
|
||||||
number: chalk.magenta,
|
|
||||||
string: chalk.green,
|
|
||||||
regex: chalk.magenta,
|
|
||||||
comment: chalk.grey,
|
|
||||||
invalid: chalk.white.bgRed.bold
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
|
||||||
const BRACKET = /^[()[\]{}]$/;
|
|
||||||
let tokenize;
|
|
||||||
{
|
|
||||||
const JSX_TAG = /^[a-z][\w-]*$/i;
|
|
||||||
|
|
||||||
const getTokenType = function (token, offset, text) {
|
|
||||||
if (token.type === "name") {
|
|
||||||
if ((0, _helperValidatorIdentifier.isKeyword)(token.value) || (0, _helperValidatorIdentifier.isStrictReservedWord)(token.value, true) || sometimesKeywords.has(token.value)) {
|
|
||||||
return "keyword";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == "</")) {
|
|
||||||
return "jsxIdentifier";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.value[0] !== token.value[0].toLowerCase()) {
|
|
||||||
return "capitalized";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.type === "punctuator" && BRACKET.test(token.value)) {
|
|
||||||
return "bracket";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
|
|
||||||
return "punctuator";
|
|
||||||
}
|
|
||||||
|
|
||||||
return token.type;
|
|
||||||
};
|
|
||||||
|
|
||||||
tokenize = function* (text) {
|
|
||||||
let match;
|
|
||||||
|
|
||||||
while (match = _jsTokens.default.exec(text)) {
|
|
||||||
const token = _jsTokens.matchToToken(match);
|
|
||||||
|
|
||||||
yield {
|
|
||||||
type: getTokenType(token, match.index, text),
|
|
||||||
value: token.value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function highlightTokens(defs, text) {
|
|
||||||
let highlighted = "";
|
|
||||||
|
|
||||||
for (const {
|
|
||||||
type,
|
|
||||||
value
|
|
||||||
} of tokenize(text)) {
|
|
||||||
const colorize = defs[type];
|
|
||||||
|
|
||||||
if (colorize) {
|
|
||||||
highlighted += value.split(NEWLINE).map(str => colorize(str)).join("\n");
|
|
||||||
} else {
|
|
||||||
highlighted += value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return highlighted;
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldHighlight(options) {
|
|
||||||
return !!_chalk.supportsColor || options.forceColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChalk(options) {
|
|
||||||
return options.forceColor ? new _chalk.constructor({
|
|
||||||
enabled: true,
|
|
||||||
level: 1
|
|
||||||
}) : _chalk;
|
|
||||||
}
|
|
||||||
|
|
||||||
function highlight(code, options = {}) {
|
|
||||||
if (shouldHighlight(options)) {
|
|
||||||
const chalk = getChalk(options);
|
|
||||||
const defs = getDefs(chalk);
|
|
||||||
return highlightTokens(defs, code);
|
|
||||||
} else {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,165 +0,0 @@
|
||||||
'use strict';
|
|
||||||
const colorConvert = require('color-convert');
|
|
||||||
|
|
||||||
const wrapAnsi16 = (fn, offset) => function () {
|
|
||||||
const code = fn.apply(colorConvert, arguments);
|
|
||||||
return `\u001B[${code + offset}m`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapAnsi256 = (fn, offset) => function () {
|
|
||||||
const code = fn.apply(colorConvert, arguments);
|
|
||||||
return `\u001B[${38 + offset};5;${code}m`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapAnsi16m = (fn, offset) => function () {
|
|
||||||
const rgb = fn.apply(colorConvert, arguments);
|
|
||||||
return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function assembleStyles() {
|
|
||||||
const codes = new Map();
|
|
||||||
const styles = {
|
|
||||||
modifier: {
|
|
||||||
reset: [0, 0],
|
|
||||||
// 21 isn't widely supported and 22 does the same thing
|
|
||||||
bold: [1, 22],
|
|
||||||
dim: [2, 22],
|
|
||||||
italic: [3, 23],
|
|
||||||
underline: [4, 24],
|
|
||||||
inverse: [7, 27],
|
|
||||||
hidden: [8, 28],
|
|
||||||
strikethrough: [9, 29]
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
black: [30, 39],
|
|
||||||
red: [31, 39],
|
|
||||||
green: [32, 39],
|
|
||||||
yellow: [33, 39],
|
|
||||||
blue: [34, 39],
|
|
||||||
magenta: [35, 39],
|
|
||||||
cyan: [36, 39],
|
|
||||||
white: [37, 39],
|
|
||||||
gray: [90, 39],
|
|
||||||
|
|
||||||
// Bright color
|
|
||||||
redBright: [91, 39],
|
|
||||||
greenBright: [92, 39],
|
|
||||||
yellowBright: [93, 39],
|
|
||||||
blueBright: [94, 39],
|
|
||||||
magentaBright: [95, 39],
|
|
||||||
cyanBright: [96, 39],
|
|
||||||
whiteBright: [97, 39]
|
|
||||||
},
|
|
||||||
bgColor: {
|
|
||||||
bgBlack: [40, 49],
|
|
||||||
bgRed: [41, 49],
|
|
||||||
bgGreen: [42, 49],
|
|
||||||
bgYellow: [43, 49],
|
|
||||||
bgBlue: [44, 49],
|
|
||||||
bgMagenta: [45, 49],
|
|
||||||
bgCyan: [46, 49],
|
|
||||||
bgWhite: [47, 49],
|
|
||||||
|
|
||||||
// Bright color
|
|
||||||
bgBlackBright: [100, 49],
|
|
||||||
bgRedBright: [101, 49],
|
|
||||||
bgGreenBright: [102, 49],
|
|
||||||
bgYellowBright: [103, 49],
|
|
||||||
bgBlueBright: [104, 49],
|
|
||||||
bgMagentaBright: [105, 49],
|
|
||||||
bgCyanBright: [106, 49],
|
|
||||||
bgWhiteBright: [107, 49]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fix humans
|
|
||||||
styles.color.grey = styles.color.gray;
|
|
||||||
|
|
||||||
for (const groupName of Object.keys(styles)) {
|
|
||||||
const group = styles[groupName];
|
|
||||||
|
|
||||||
for (const styleName of Object.keys(group)) {
|
|
||||||
const style = group[styleName];
|
|
||||||
|
|
||||||
styles[styleName] = {
|
|
||||||
open: `\u001B[${style[0]}m`,
|
|
||||||
close: `\u001B[${style[1]}m`
|
|
||||||
};
|
|
||||||
|
|
||||||
group[styleName] = styles[styleName];
|
|
||||||
|
|
||||||
codes.set(style[0], style[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(styles, groupName, {
|
|
||||||
value: group,
|
|
||||||
enumerable: false
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(styles, 'codes', {
|
|
||||||
value: codes,
|
|
||||||
enumerable: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const ansi2ansi = n => n;
|
|
||||||
const rgb2rgb = (r, g, b) => [r, g, b];
|
|
||||||
|
|
||||||
styles.color.close = '\u001B[39m';
|
|
||||||
styles.bgColor.close = '\u001B[49m';
|
|
||||||
|
|
||||||
styles.color.ansi = {
|
|
||||||
ansi: wrapAnsi16(ansi2ansi, 0)
|
|
||||||
};
|
|
||||||
styles.color.ansi256 = {
|
|
||||||
ansi256: wrapAnsi256(ansi2ansi, 0)
|
|
||||||
};
|
|
||||||
styles.color.ansi16m = {
|
|
||||||
rgb: wrapAnsi16m(rgb2rgb, 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.bgColor.ansi = {
|
|
||||||
ansi: wrapAnsi16(ansi2ansi, 10)
|
|
||||||
};
|
|
||||||
styles.bgColor.ansi256 = {
|
|
||||||
ansi256: wrapAnsi256(ansi2ansi, 10)
|
|
||||||
};
|
|
||||||
styles.bgColor.ansi16m = {
|
|
||||||
rgb: wrapAnsi16m(rgb2rgb, 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
for (let key of Object.keys(colorConvert)) {
|
|
||||||
if (typeof colorConvert[key] !== 'object') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const suite = colorConvert[key];
|
|
||||||
|
|
||||||
if (key === 'ansi16') {
|
|
||||||
key = 'ansi';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('ansi16' in suite) {
|
|
||||||
styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0);
|
|
||||||
styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('ansi256' in suite) {
|
|
||||||
styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0);
|
|
||||||
styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('rgb' in suite) {
|
|
||||||
styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0);
|
|
||||||
styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return styles;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the export immutable
|
|
||||||
Object.defineProperty(module, 'exports', {
|
|
||||||
enumerable: true,
|
|
||||||
get: assembleStyles
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,56 +0,0 @@
|
||||||
{
|
|
||||||
"name": "ansi-styles",
|
|
||||||
"version": "3.2.1",
|
|
||||||
"description": "ANSI escape codes for styling strings in the terminal",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": "chalk/ansi-styles",
|
|
||||||
"author": {
|
|
||||||
"name": "Sindre Sorhus",
|
|
||||||
"email": "sindresorhus@gmail.com",
|
|
||||||
"url": "sindresorhus.com"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "xo && ava",
|
|
||||||
"screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"index.js"
|
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"ansi",
|
|
||||||
"styles",
|
|
||||||
"color",
|
|
||||||
"colour",
|
|
||||||
"colors",
|
|
||||||
"terminal",
|
|
||||||
"console",
|
|
||||||
"cli",
|
|
||||||
"string",
|
|
||||||
"tty",
|
|
||||||
"escape",
|
|
||||||
"formatting",
|
|
||||||
"rgb",
|
|
||||||
"256",
|
|
||||||
"shell",
|
|
||||||
"xterm",
|
|
||||||
"log",
|
|
||||||
"logging",
|
|
||||||
"command-line",
|
|
||||||
"text"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"ava": "*",
|
|
||||||
"babel-polyfill": "^6.23.0",
|
|
||||||
"svg-term-cli": "^2.1.1",
|
|
||||||
"xo": "*"
|
|
||||||
},
|
|
||||||
"ava": {
|
|
||||||
"require": "babel-polyfill"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles)
|
|
||||||
|
|
||||||
> [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
|
|
||||||
|
|
||||||
You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
|
|
||||||
|
|
||||||
<img src="https://cdn.rawgit.com/chalk/ansi-styles/8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
|
|
||||||
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
```
|
|
||||||
$ npm install ansi-styles
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
const style = require('ansi-styles');
|
|
||||||
|
|
||||||
console.log(`${style.green.open}Hello world!${style.green.close}`);
|
|
||||||
|
|
||||||
|
|
||||||
// Color conversion between 16/256/truecolor
|
|
||||||
// NOTE: If conversion goes to 16 colors or 256 colors, the original color
|
|
||||||
// may be degraded to fit that color palette. This means terminals
|
|
||||||
// that do not support 16 million colors will best-match the
|
|
||||||
// original color.
|
|
||||||
console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
|
|
||||||
console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
|
|
||||||
console.log(style.color.ansi16m.hex('#ABCDEF') + 'Hello world!' + style.color.close);
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
Each style has an `open` and `close` property.
|
|
||||||
|
|
||||||
|
|
||||||
## Styles
|
|
||||||
|
|
||||||
### Modifiers
|
|
||||||
|
|
||||||
- `reset`
|
|
||||||
- `bold`
|
|
||||||
- `dim`
|
|
||||||
- `italic` *(Not widely supported)*
|
|
||||||
- `underline`
|
|
||||||
- `inverse`
|
|
||||||
- `hidden`
|
|
||||||
- `strikethrough` *(Not widely supported)*
|
|
||||||
|
|
||||||
### Colors
|
|
||||||
|
|
||||||
- `black`
|
|
||||||
- `red`
|
|
||||||
- `green`
|
|
||||||
- `yellow`
|
|
||||||
- `blue`
|
|
||||||
- `magenta`
|
|
||||||
- `cyan`
|
|
||||||
- `white`
|
|
||||||
- `gray` ("bright black")
|
|
||||||
- `redBright`
|
|
||||||
- `greenBright`
|
|
||||||
- `yellowBright`
|
|
||||||
- `blueBright`
|
|
||||||
- `magentaBright`
|
|
||||||
- `cyanBright`
|
|
||||||
- `whiteBright`
|
|
||||||
|
|
||||||
### Background colors
|
|
||||||
|
|
||||||
- `bgBlack`
|
|
||||||
- `bgRed`
|
|
||||||
- `bgGreen`
|
|
||||||
- `bgYellow`
|
|
||||||
- `bgBlue`
|
|
||||||
- `bgMagenta`
|
|
||||||
- `bgCyan`
|
|
||||||
- `bgWhite`
|
|
||||||
- `bgBlackBright`
|
|
||||||
- `bgRedBright`
|
|
||||||
- `bgGreenBright`
|
|
||||||
- `bgYellowBright`
|
|
||||||
- `bgBlueBright`
|
|
||||||
- `bgMagentaBright`
|
|
||||||
- `bgCyanBright`
|
|
||||||
- `bgWhiteBright`
|
|
||||||
|
|
||||||
|
|
||||||
## Advanced usage
|
|
||||||
|
|
||||||
By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
|
|
||||||
|
|
||||||
- `style.modifier`
|
|
||||||
- `style.color`
|
|
||||||
- `style.bgColor`
|
|
||||||
|
|
||||||
###### Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
console.log(style.color.green.open);
|
|
||||||
```
|
|
||||||
|
|
||||||
Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values.
|
|
||||||
|
|
||||||
###### Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
console.log(style.codes.get(36));
|
|
||||||
//=> 39
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
|
|
||||||
|
|
||||||
`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
|
|
||||||
|
|
||||||
To use these, call the associated conversion function with the intended output, for example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code
|
|
||||||
style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code
|
|
||||||
|
|
||||||
style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
|
|
||||||
style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
|
|
||||||
|
|
||||||
style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code
|
|
||||||
style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
|
|
||||||
|
|
||||||
|
|
||||||
## Maintainers
|
|
||||||
|
|
||||||
- [Sindre Sorhus](https://github.com/sindresorhus)
|
|
||||||
- [Josh Junon](https://github.com/qix-)
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,228 +0,0 @@
|
||||||
'use strict';
|
|
||||||
const escapeStringRegexp = require('escape-string-regexp');
|
|
||||||
const ansiStyles = require('ansi-styles');
|
|
||||||
const stdoutColor = require('supports-color').stdout;
|
|
||||||
|
|
||||||
const template = require('./templates.js');
|
|
||||||
|
|
||||||
const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
|
|
||||||
|
|
||||||
// `supportsColor.level` → `ansiStyles.color[name]` mapping
|
|
||||||
const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m'];
|
|
||||||
|
|
||||||
// `color-convert` models to exclude from the Chalk API due to conflicts and such
|
|
||||||
const skipModels = new Set(['gray']);
|
|
||||||
|
|
||||||
const styles = Object.create(null);
|
|
||||||
|
|
||||||
function applyOptions(obj, options) {
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
// Detect level if not set manually
|
|
||||||
const scLevel = stdoutColor ? stdoutColor.level : 0;
|
|
||||||
obj.level = options.level === undefined ? scLevel : options.level;
|
|
||||||
obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Chalk(options) {
|
|
||||||
// We check for this.template here since calling `chalk.constructor()`
|
|
||||||
// by itself will have a `this` of a previously constructed chalk object
|
|
||||||
if (!this || !(this instanceof Chalk) || this.template) {
|
|
||||||
const chalk = {};
|
|
||||||
applyOptions(chalk, options);
|
|
||||||
|
|
||||||
chalk.template = function () {
|
|
||||||
const args = [].slice.call(arguments);
|
|
||||||
return chalkTag.apply(null, [chalk.template].concat(args));
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.setPrototypeOf(chalk, Chalk.prototype);
|
|
||||||
Object.setPrototypeOf(chalk.template, chalk);
|
|
||||||
|
|
||||||
chalk.template.constructor = Chalk;
|
|
||||||
|
|
||||||
return chalk.template;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyOptions(this, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use bright blue on Windows as the normal blue color is illegible
|
|
||||||
if (isSimpleWindowsTerm) {
|
|
||||||
ansiStyles.blue.open = '\u001B[94m';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key of Object.keys(ansiStyles)) {
|
|
||||||
ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
|
|
||||||
|
|
||||||
styles[key] = {
|
|
||||||
get() {
|
|
||||||
const codes = ansiStyles[key];
|
|
||||||
return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.visible = {
|
|
||||||
get() {
|
|
||||||
return build.call(this, this._styles || [], true, 'visible');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g');
|
|
||||||
for (const model of Object.keys(ansiStyles.color.ansi)) {
|
|
||||||
if (skipModels.has(model)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
styles[model] = {
|
|
||||||
get() {
|
|
||||||
const level = this.level;
|
|
||||||
return function () {
|
|
||||||
const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments);
|
|
||||||
const codes = {
|
|
||||||
open,
|
|
||||||
close: ansiStyles.color.close,
|
|
||||||
closeRe: ansiStyles.color.closeRe
|
|
||||||
};
|
|
||||||
return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g');
|
|
||||||
for (const model of Object.keys(ansiStyles.bgColor.ansi)) {
|
|
||||||
if (skipModels.has(model)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
|
|
||||||
styles[bgModel] = {
|
|
||||||
get() {
|
|
||||||
const level = this.level;
|
|
||||||
return function () {
|
|
||||||
const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments);
|
|
||||||
const codes = {
|
|
||||||
open,
|
|
||||||
close: ansiStyles.bgColor.close,
|
|
||||||
closeRe: ansiStyles.bgColor.closeRe
|
|
||||||
};
|
|
||||||
return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const proto = Object.defineProperties(() => {}, styles);
|
|
||||||
|
|
||||||
function build(_styles, _empty, key) {
|
|
||||||
const builder = function () {
|
|
||||||
return applyStyle.apply(builder, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
builder._styles = _styles;
|
|
||||||
builder._empty = _empty;
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
Object.defineProperty(builder, 'level', {
|
|
||||||
enumerable: true,
|
|
||||||
get() {
|
|
||||||
return self.level;
|
|
||||||
},
|
|
||||||
set(level) {
|
|
||||||
self.level = level;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(builder, 'enabled', {
|
|
||||||
enumerable: true,
|
|
||||||
get() {
|
|
||||||
return self.enabled;
|
|
||||||
},
|
|
||||||
set(enabled) {
|
|
||||||
self.enabled = enabled;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// See below for fix regarding invisible grey/dim combination on Windows
|
|
||||||
builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey';
|
|
||||||
|
|
||||||
// `__proto__` is used because we must return a function, but there is
|
|
||||||
// no way to create a function with a different prototype
|
|
||||||
builder.__proto__ = proto; // eslint-disable-line no-proto
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyStyle() {
|
|
||||||
// Support varags, but simply cast to string in case there's only one arg
|
|
||||||
const args = arguments;
|
|
||||||
const argsLen = args.length;
|
|
||||||
let str = String(arguments[0]);
|
|
||||||
|
|
||||||
if (argsLen === 0) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argsLen > 1) {
|
|
||||||
// Don't slice `arguments`, it prevents V8 optimizations
|
|
||||||
for (let a = 1; a < argsLen; a++) {
|
|
||||||
str += ' ' + args[a];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.enabled || this.level <= 0 || !str) {
|
|
||||||
return this._empty ? '' : str;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
|
|
||||||
// see https://github.com/chalk/chalk/issues/58
|
|
||||||
// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
|
|
||||||
const originalDim = ansiStyles.dim.open;
|
|
||||||
if (isSimpleWindowsTerm && this.hasGrey) {
|
|
||||||
ansiStyles.dim.open = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const code of this._styles.slice().reverse()) {
|
|
||||||
// Replace any instances already present with a re-opening code
|
|
||||||
// otherwise only the part of the string until said closing code
|
|
||||||
// will be colored, and the rest will simply be 'plain'.
|
|
||||||
str = code.open + str.replace(code.closeRe, code.open) + code.close;
|
|
||||||
|
|
||||||
// Close the styling before a linebreak and reopen
|
|
||||||
// after next line to fix a bleed issue on macOS
|
|
||||||
// https://github.com/chalk/chalk/pull/92
|
|
||||||
str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the original `dim` if we changed it to work around the Windows dimmed gray issue
|
|
||||||
ansiStyles.dim.open = originalDim;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function chalkTag(chalk, strings) {
|
|
||||||
if (!Array.isArray(strings)) {
|
|
||||||
// If chalk() was called by itself or with a string,
|
|
||||||
// return the string itself as a string.
|
|
||||||
return [].slice.call(arguments, 1).join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
const args = [].slice.call(arguments, 2);
|
|
||||||
const parts = [strings.raw[0]];
|
|
||||||
|
|
||||||
for (let i = 1; i < strings.length; i++) {
|
|
||||||
parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&'));
|
|
||||||
parts.push(String(strings.raw[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return template(chalk, parts.join(''));
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperties(Chalk.prototype, styles);
|
|
||||||
|
|
||||||
module.exports = Chalk(); // eslint-disable-line new-cap
|
|
||||||
module.exports.supportsColor = stdoutColor;
|
|
||||||
module.exports.default = module.exports; // For TypeScript
|
|
|
@ -1,93 +0,0 @@
|
||||||
// @flow strict
|
|
||||||
|
|
||||||
type TemplateStringsArray = $ReadOnlyArray<string>;
|
|
||||||
|
|
||||||
export type Level = $Values<{
|
|
||||||
None: 0,
|
|
||||||
Basic: 1,
|
|
||||||
Ansi256: 2,
|
|
||||||
TrueColor: 3
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export type ChalkOptions = {|
|
|
||||||
enabled?: boolean,
|
|
||||||
level?: Level
|
|
||||||
|};
|
|
||||||
|
|
||||||
export type ColorSupport = {|
|
|
||||||
level: Level,
|
|
||||||
hasBasic: boolean,
|
|
||||||
has256: boolean,
|
|
||||||
has16m: boolean
|
|
||||||
|};
|
|
||||||
|
|
||||||
export interface Chalk {
|
|
||||||
(...text: string[]): string,
|
|
||||||
(text: TemplateStringsArray, ...placeholders: string[]): string,
|
|
||||||
constructor(options?: ChalkOptions): Chalk,
|
|
||||||
enabled: boolean,
|
|
||||||
level: Level,
|
|
||||||
rgb(r: number, g: number, b: number): Chalk,
|
|
||||||
hsl(h: number, s: number, l: number): Chalk,
|
|
||||||
hsv(h: number, s: number, v: number): Chalk,
|
|
||||||
hwb(h: number, w: number, b: number): Chalk,
|
|
||||||
bgHex(color: string): Chalk,
|
|
||||||
bgKeyword(color: string): Chalk,
|
|
||||||
bgRgb(r: number, g: number, b: number): Chalk,
|
|
||||||
bgHsl(h: number, s: number, l: number): Chalk,
|
|
||||||
bgHsv(h: number, s: number, v: number): Chalk,
|
|
||||||
bgHwb(h: number, w: number, b: number): Chalk,
|
|
||||||
hex(color: string): Chalk,
|
|
||||||
keyword(color: string): Chalk,
|
|
||||||
|
|
||||||
+reset: Chalk,
|
|
||||||
+bold: Chalk,
|
|
||||||
+dim: Chalk,
|
|
||||||
+italic: Chalk,
|
|
||||||
+underline: Chalk,
|
|
||||||
+inverse: Chalk,
|
|
||||||
+hidden: Chalk,
|
|
||||||
+strikethrough: Chalk,
|
|
||||||
|
|
||||||
+visible: Chalk,
|
|
||||||
|
|
||||||
+black: Chalk,
|
|
||||||
+red: Chalk,
|
|
||||||
+green: Chalk,
|
|
||||||
+yellow: Chalk,
|
|
||||||
+blue: Chalk,
|
|
||||||
+magenta: Chalk,
|
|
||||||
+cyan: Chalk,
|
|
||||||
+white: Chalk,
|
|
||||||
+gray: Chalk,
|
|
||||||
+grey: Chalk,
|
|
||||||
+blackBright: Chalk,
|
|
||||||
+redBright: Chalk,
|
|
||||||
+greenBright: Chalk,
|
|
||||||
+yellowBright: Chalk,
|
|
||||||
+blueBright: Chalk,
|
|
||||||
+magentaBright: Chalk,
|
|
||||||
+cyanBright: Chalk,
|
|
||||||
+whiteBright: Chalk,
|
|
||||||
|
|
||||||
+bgBlack: Chalk,
|
|
||||||
+bgRed: Chalk,
|
|
||||||
+bgGreen: Chalk,
|
|
||||||
+bgYellow: Chalk,
|
|
||||||
+bgBlue: Chalk,
|
|
||||||
+bgMagenta: Chalk,
|
|
||||||
+bgCyan: Chalk,
|
|
||||||
+bgWhite: Chalk,
|
|
||||||
+bgBlackBright: Chalk,
|
|
||||||
+bgRedBright: Chalk,
|
|
||||||
+bgGreenBright: Chalk,
|
|
||||||
+bgYellowBright: Chalk,
|
|
||||||
+bgBlueBright: Chalk,
|
|
||||||
+bgMagentaBright: Chalk,
|
|
||||||
+bgCyanBright: Chalk,
|
|
||||||
+bgWhiteBrigh: Chalk,
|
|
||||||
|
|
||||||
supportsColor: ColorSupport
|
|
||||||
};
|
|
||||||
|
|
||||||
declare module.exports: Chalk;
|
|
|
@ -1,9 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,71 +0,0 @@
|
||||||
{
|
|
||||||
"name": "chalk",
|
|
||||||
"version": "2.4.2",
|
|
||||||
"description": "Terminal string styling done right",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": "chalk/chalk",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "xo && tsc --project types && flow --max-warnings=0 && nyc ava",
|
|
||||||
"bench": "matcha benchmark.js",
|
|
||||||
"coveralls": "nyc report --reporter=text-lcov | coveralls"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"index.js",
|
|
||||||
"templates.js",
|
|
||||||
"types/index.d.ts",
|
|
||||||
"index.js.flow"
|
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"color",
|
|
||||||
"colour",
|
|
||||||
"colors",
|
|
||||||
"terminal",
|
|
||||||
"console",
|
|
||||||
"cli",
|
|
||||||
"string",
|
|
||||||
"str",
|
|
||||||
"ansi",
|
|
||||||
"style",
|
|
||||||
"styles",
|
|
||||||
"tty",
|
|
||||||
"formatting",
|
|
||||||
"rgb",
|
|
||||||
"256",
|
|
||||||
"shell",
|
|
||||||
"xterm",
|
|
||||||
"log",
|
|
||||||
"logging",
|
|
||||||
"command-line",
|
|
||||||
"text"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"ava": "*",
|
|
||||||
"coveralls": "^3.0.0",
|
|
||||||
"execa": "^0.9.0",
|
|
||||||
"flow-bin": "^0.68.0",
|
|
||||||
"import-fresh": "^2.0.0",
|
|
||||||
"matcha": "^0.7.0",
|
|
||||||
"nyc": "^11.0.2",
|
|
||||||
"resolve-from": "^4.0.0",
|
|
||||||
"typescript": "^2.5.3",
|
|
||||||
"xo": "*"
|
|
||||||
},
|
|
||||||
"types": "types/index.d.ts",
|
|
||||||
"xo": {
|
|
||||||
"envs": [
|
|
||||||
"node",
|
|
||||||
"mocha"
|
|
||||||
],
|
|
||||||
"ignores": [
|
|
||||||
"test/_flow.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,314 +0,0 @@
|
||||||
<h1 align="center">
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<img width="320" src="media/logo.svg" alt="Chalk">
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
> Terminal string styling done right
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) [![Mentioned in Awesome Node.js](https://awesome.re/mentioned-badge.svg)](https://github.com/sindresorhus/awesome-nodejs)
|
|
||||||
|
|
||||||
### [See what's new in Chalk 2](https://github.com/chalk/chalk/releases/tag/v2.0.0)
|
|
||||||
|
|
||||||
<img src="https://cdn.rawgit.com/chalk/ansi-styles/8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" alt="" width="900">
|
|
||||||
|
|
||||||
|
|
||||||
## Highlights
|
|
||||||
|
|
||||||
- Expressive API
|
|
||||||
- Highly performant
|
|
||||||
- Ability to nest styles
|
|
||||||
- [256/Truecolor color support](#256-and-truecolor-color-support)
|
|
||||||
- Auto-detects color support
|
|
||||||
- Doesn't extend `String.prototype`
|
|
||||||
- Clean and focused
|
|
||||||
- Actively maintained
|
|
||||||
- [Used by ~23,000 packages](https://www.npmjs.com/browse/depended/chalk) as of December 31, 2017
|
|
||||||
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ npm install chalk
|
|
||||||
```
|
|
||||||
|
|
||||||
<a href="https://www.patreon.com/sindresorhus">
|
|
||||||
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
|
|
||||||
</a>
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
const chalk = require('chalk');
|
|
||||||
|
|
||||||
console.log(chalk.blue('Hello world!'));
|
|
||||||
```
|
|
||||||
|
|
||||||
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
|
|
||||||
|
|
||||||
```js
|
|
||||||
const chalk = require('chalk');
|
|
||||||
const log = console.log;
|
|
||||||
|
|
||||||
// Combine styled and normal strings
|
|
||||||
log(chalk.blue('Hello') + ' World' + chalk.red('!'));
|
|
||||||
|
|
||||||
// Compose multiple styles using the chainable API
|
|
||||||
log(chalk.blue.bgRed.bold('Hello world!'));
|
|
||||||
|
|
||||||
// Pass in multiple arguments
|
|
||||||
log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
|
|
||||||
|
|
||||||
// Nest styles
|
|
||||||
log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
|
|
||||||
|
|
||||||
// Nest styles of the same type even (color, underline, background)
|
|
||||||
log(chalk.green(
|
|
||||||
'I am a green line ' +
|
|
||||||
chalk.blue.underline.bold('with a blue substring') +
|
|
||||||
' that becomes green again!'
|
|
||||||
));
|
|
||||||
|
|
||||||
// ES2015 template literal
|
|
||||||
log(`
|
|
||||||
CPU: ${chalk.red('90%')}
|
|
||||||
RAM: ${chalk.green('40%')}
|
|
||||||
DISK: ${chalk.yellow('70%')}
|
|
||||||
`);
|
|
||||||
|
|
||||||
// ES2015 tagged template literal
|
|
||||||
log(chalk`
|
|
||||||
CPU: {red ${cpu.totalPercent}%}
|
|
||||||
RAM: {green ${ram.used / ram.total * 100}%}
|
|
||||||
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
|
|
||||||
`);
|
|
||||||
|
|
||||||
// Use RGB colors in terminal emulators that support it.
|
|
||||||
log(chalk.keyword('orange')('Yay for orange colored text!'));
|
|
||||||
log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
|
|
||||||
log(chalk.hex('#DEADED').bold('Bold gray!'));
|
|
||||||
```
|
|
||||||
|
|
||||||
Easily define your own themes:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const chalk = require('chalk');
|
|
||||||
|
|
||||||
const error = chalk.bold.red;
|
|
||||||
const warning = chalk.keyword('orange');
|
|
||||||
|
|
||||||
console.log(error('Error!'));
|
|
||||||
console.log(warning('Warning!'));
|
|
||||||
```
|
|
||||||
|
|
||||||
Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
|
|
||||||
|
|
||||||
```js
|
|
||||||
const name = 'Sindre';
|
|
||||||
console.log(chalk.green('Hello %s'), name);
|
|
||||||
//=> 'Hello Sindre'
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### chalk.`<style>[.<style>...](string, [string...])`
|
|
||||||
|
|
||||||
Example: `chalk.red.bold.underline('Hello', 'world');`
|
|
||||||
|
|
||||||
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
|
|
||||||
|
|
||||||
Multiple arguments will be separated by space.
|
|
||||||
|
|
||||||
### chalk.enabled
|
|
||||||
|
|
||||||
Color support is automatically detected, as is the level (see `chalk.level`). However, if you'd like to simply enable/disable Chalk, you can do so via the `.enabled` property.
|
|
||||||
|
|
||||||
Chalk is enabled by default unless explicitly disabled via the constructor or `chalk.level` is `0`.
|
|
||||||
|
|
||||||
If you need to change this in a reusable module, create a new instance:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const ctx = new chalk.constructor({enabled: false});
|
|
||||||
```
|
|
||||||
|
|
||||||
### chalk.level
|
|
||||||
|
|
||||||
Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
|
|
||||||
|
|
||||||
If you need to change this in a reusable module, create a new instance:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const ctx = new chalk.constructor({level: 0});
|
|
||||||
```
|
|
||||||
|
|
||||||
Levels are as follows:
|
|
||||||
|
|
||||||
0. All colors disabled
|
|
||||||
1. Basic color support (16 colors)
|
|
||||||
2. 256 color support
|
|
||||||
3. Truecolor support (16 million colors)
|
|
||||||
|
|
||||||
### chalk.supportsColor
|
|
||||||
|
|
||||||
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
|
|
||||||
|
|
||||||
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
|
|
||||||
|
|
||||||
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
|
|
||||||
|
|
||||||
|
|
||||||
## Styles
|
|
||||||
|
|
||||||
### Modifiers
|
|
||||||
|
|
||||||
- `reset`
|
|
||||||
- `bold`
|
|
||||||
- `dim`
|
|
||||||
- `italic` *(Not widely supported)*
|
|
||||||
- `underline`
|
|
||||||
- `inverse`
|
|
||||||
- `hidden`
|
|
||||||
- `strikethrough` *(Not widely supported)*
|
|
||||||
- `visible` (Text is emitted only if enabled)
|
|
||||||
|
|
||||||
### Colors
|
|
||||||
|
|
||||||
- `black`
|
|
||||||
- `red`
|
|
||||||
- `green`
|
|
||||||
- `yellow`
|
|
||||||
- `blue` *(On Windows the bright version is used since normal blue is illegible)*
|
|
||||||
- `magenta`
|
|
||||||
- `cyan`
|
|
||||||
- `white`
|
|
||||||
- `gray` ("bright black")
|
|
||||||
- `redBright`
|
|
||||||
- `greenBright`
|
|
||||||
- `yellowBright`
|
|
||||||
- `blueBright`
|
|
||||||
- `magentaBright`
|
|
||||||
- `cyanBright`
|
|
||||||
- `whiteBright`
|
|
||||||
|
|
||||||
### Background colors
|
|
||||||
|
|
||||||
- `bgBlack`
|
|
||||||
- `bgRed`
|
|
||||||
- `bgGreen`
|
|
||||||
- `bgYellow`
|
|
||||||
- `bgBlue`
|
|
||||||
- `bgMagenta`
|
|
||||||
- `bgCyan`
|
|
||||||
- `bgWhite`
|
|
||||||
- `bgBlackBright`
|
|
||||||
- `bgRedBright`
|
|
||||||
- `bgGreenBright`
|
|
||||||
- `bgYellowBright`
|
|
||||||
- `bgBlueBright`
|
|
||||||
- `bgMagentaBright`
|
|
||||||
- `bgCyanBright`
|
|
||||||
- `bgWhiteBright`
|
|
||||||
|
|
||||||
|
|
||||||
## Tagged template literal
|
|
||||||
|
|
||||||
Chalk can be used as a [tagged template literal](http://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
|
|
||||||
|
|
||||||
```js
|
|
||||||
const chalk = require('chalk');
|
|
||||||
|
|
||||||
const miles = 18;
|
|
||||||
const calculateFeet = miles => miles * 5280;
|
|
||||||
|
|
||||||
console.log(chalk`
|
|
||||||
There are {bold 5280 feet} in a mile.
|
|
||||||
In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
|
|
||||||
`);
|
|
||||||
```
|
|
||||||
|
|
||||||
Blocks are delimited by an opening curly brace (`{`), a style, some content, and a closing curly brace (`}`).
|
|
||||||
|
|
||||||
Template styles are chained exactly like normal Chalk styles. The following two statements are equivalent:
|
|
||||||
|
|
||||||
```js
|
|
||||||
console.log(chalk.bold.rgb(10, 100, 200)('Hello!'));
|
|
||||||
console.log(chalk`{bold.rgb(10,100,200) Hello!}`);
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that function styles (`rgb()`, `hsl()`, `keyword()`, etc.) may not contain spaces between parameters.
|
|
||||||
|
|
||||||
All interpolated values (`` chalk`${foo}` ``) are converted to strings via the `.toString()` method. All curly braces (`{` and `}`) in interpolated value strings are escaped.
|
|
||||||
|
|
||||||
|
|
||||||
## 256 and Truecolor color support
|
|
||||||
|
|
||||||
Chalk supports 256 colors and [Truecolor](https://gist.github.com/XVilka/8346728) (16 million colors) on supported terminal apps.
|
|
||||||
|
|
||||||
Colors are downsampled from 16 million RGB values to an ANSI color format that is supported by the terminal emulator (or by specifying `{level: n}` as a Chalk option). For example, Chalk configured to run at level 1 (basic color support) will downsample an RGB value of #FF0000 (red) to 31 (ANSI escape for red).
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- `chalk.hex('#DEADED').underline('Hello, world!')`
|
|
||||||
- `chalk.keyword('orange')('Some orange text')`
|
|
||||||
- `chalk.rgb(15, 100, 204).inverse('Hello!')`
|
|
||||||
|
|
||||||
Background versions of these models are prefixed with `bg` and the first level of the module capitalized (e.g. `keyword` for foreground colors and `bgKeyword` for background colors).
|
|
||||||
|
|
||||||
- `chalk.bgHex('#DEADED').underline('Hello, world!')`
|
|
||||||
- `chalk.bgKeyword('orange')('Some orange text')`
|
|
||||||
- `chalk.bgRgb(15, 100, 204).inverse('Hello!')`
|
|
||||||
|
|
||||||
The following color models can be used:
|
|
||||||
|
|
||||||
- [`rgb`](https://en.wikipedia.org/wiki/RGB_color_model) - Example: `chalk.rgb(255, 136, 0).bold('Orange!')`
|
|
||||||
- [`hex`](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) - Example: `chalk.hex('#FF8800').bold('Orange!')`
|
|
||||||
- [`keyword`](https://www.w3.org/wiki/CSS/Properties/color/keywords) (CSS keywords) - Example: `chalk.keyword('orange').bold('Orange!')`
|
|
||||||
- [`hsl`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsl(32, 100, 50).bold('Orange!')`
|
|
||||||
- [`hsv`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsv(32, 100, 100).bold('Orange!')`
|
|
||||||
- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model) - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
|
|
||||||
- `ansi16`
|
|
||||||
- `ansi256`
|
|
||||||
|
|
||||||
|
|
||||||
## Windows
|
|
||||||
|
|
||||||
If you're on Windows, do yourself a favor and use [`cmder`](http://cmder.net/) instead of `cmd.exe`.
|
|
||||||
|
|
||||||
|
|
||||||
## Origin story
|
|
||||||
|
|
||||||
[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68) and the package is unmaintained. Although there are other packages, they either do too much or not enough. Chalk is a clean and focused alternative.
|
|
||||||
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
|
|
||||||
- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
|
|
||||||
- [supports-color](https://github.com/chalk/supports-color) - Detect whether a terminal supports color
|
|
||||||
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
|
|
||||||
- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Strip ANSI escape codes from a stream
|
|
||||||
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
|
|
||||||
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
|
|
||||||
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
|
|
||||||
- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
|
|
||||||
- [color-convert](https://github.com/qix-/color-convert) - Converts colors between different models
|
|
||||||
- [chalk-animation](https://github.com/bokub/chalk-animation) - Animate strings in the terminal
|
|
||||||
- [gradient-string](https://github.com/bokub/gradient-string) - Apply color gradients to strings
|
|
||||||
- [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
|
|
||||||
- [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
|
|
||||||
|
|
||||||
|
|
||||||
## Maintainers
|
|
||||||
|
|
||||||
- [Sindre Sorhus](https://github.com/sindresorhus)
|
|
||||||
- [Josh Junon](https://github.com/qix-)
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,128 +0,0 @@
|
||||||
'use strict';
|
|
||||||
const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
|
|
||||||
const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
|
|
||||||
const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
|
|
||||||
const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi;
|
|
||||||
|
|
||||||
const ESCAPES = new Map([
|
|
||||||
['n', '\n'],
|
|
||||||
['r', '\r'],
|
|
||||||
['t', '\t'],
|
|
||||||
['b', '\b'],
|
|
||||||
['f', '\f'],
|
|
||||||
['v', '\v'],
|
|
||||||
['0', '\0'],
|
|
||||||
['\\', '\\'],
|
|
||||||
['e', '\u001B'],
|
|
||||||
['a', '\u0007']
|
|
||||||
]);
|
|
||||||
|
|
||||||
function unescape(c) {
|
|
||||||
if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
|
|
||||||
return String.fromCharCode(parseInt(c.slice(1), 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESCAPES.get(c) || c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseArguments(name, args) {
|
|
||||||
const results = [];
|
|
||||||
const chunks = args.trim().split(/\s*,\s*/g);
|
|
||||||
let matches;
|
|
||||||
|
|
||||||
for (const chunk of chunks) {
|
|
||||||
if (!isNaN(chunk)) {
|
|
||||||
results.push(Number(chunk));
|
|
||||||
} else if ((matches = chunk.match(STRING_REGEX))) {
|
|
||||||
results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr));
|
|
||||||
} else {
|
|
||||||
throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseStyle(style) {
|
|
||||||
STYLE_REGEX.lastIndex = 0;
|
|
||||||
|
|
||||||
const results = [];
|
|
||||||
let matches;
|
|
||||||
|
|
||||||
while ((matches = STYLE_REGEX.exec(style)) !== null) {
|
|
||||||
const name = matches[1];
|
|
||||||
|
|
||||||
if (matches[2]) {
|
|
||||||
const args = parseArguments(name, matches[2]);
|
|
||||||
results.push([name].concat(args));
|
|
||||||
} else {
|
|
||||||
results.push([name]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildStyle(chalk, styles) {
|
|
||||||
const enabled = {};
|
|
||||||
|
|
||||||
for (const layer of styles) {
|
|
||||||
for (const style of layer.styles) {
|
|
||||||
enabled[style[0]] = layer.inverse ? null : style.slice(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let current = chalk;
|
|
||||||
for (const styleName of Object.keys(enabled)) {
|
|
||||||
if (Array.isArray(enabled[styleName])) {
|
|
||||||
if (!(styleName in current)) {
|
|
||||||
throw new Error(`Unknown Chalk style: ${styleName}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabled[styleName].length > 0) {
|
|
||||||
current = current[styleName].apply(current, enabled[styleName]);
|
|
||||||
} else {
|
|
||||||
current = current[styleName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = (chalk, tmp) => {
|
|
||||||
const styles = [];
|
|
||||||
const chunks = [];
|
|
||||||
let chunk = [];
|
|
||||||
|
|
||||||
// eslint-disable-next-line max-params
|
|
||||||
tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => {
|
|
||||||
if (escapeChar) {
|
|
||||||
chunk.push(unescape(escapeChar));
|
|
||||||
} else if (style) {
|
|
||||||
const str = chunk.join('');
|
|
||||||
chunk = [];
|
|
||||||
chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str));
|
|
||||||
styles.push({inverse, styles: parseStyle(style)});
|
|
||||||
} else if (close) {
|
|
||||||
if (styles.length === 0) {
|
|
||||||
throw new Error('Found extraneous } in Chalk template literal');
|
|
||||||
}
|
|
||||||
|
|
||||||
chunks.push(buildStyle(chalk, styles)(chunk.join('')));
|
|
||||||
chunk = [];
|
|
||||||
styles.pop();
|
|
||||||
} else {
|
|
||||||
chunk.push(chr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
chunks.push(chunk.join(''));
|
|
||||||
|
|
||||||
if (styles.length > 0) {
|
|
||||||
const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
|
|
||||||
throw new Error(errMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return chunks.join('');
|
|
||||||
};
|
|
|
@ -1,97 +0,0 @@
|
||||||
// Type definitions for Chalk
|
|
||||||
// Definitions by: Thomas Sauer <https://github.com/t-sauer>
|
|
||||||
|
|
||||||
export const enum Level {
|
|
||||||
None = 0,
|
|
||||||
Basic = 1,
|
|
||||||
Ansi256 = 2,
|
|
||||||
TrueColor = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChalkOptions {
|
|
||||||
enabled?: boolean;
|
|
||||||
level?: Level;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChalkConstructor {
|
|
||||||
new (options?: ChalkOptions): Chalk;
|
|
||||||
(options?: ChalkOptions): Chalk;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ColorSupport {
|
|
||||||
level: Level;
|
|
||||||
hasBasic: boolean;
|
|
||||||
has256: boolean;
|
|
||||||
has16m: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Chalk {
|
|
||||||
(...text: string[]): string;
|
|
||||||
(text: TemplateStringsArray, ...placeholders: string[]): string;
|
|
||||||
constructor: ChalkConstructor;
|
|
||||||
enabled: boolean;
|
|
||||||
level: Level;
|
|
||||||
rgb(r: number, g: number, b: number): this;
|
|
||||||
hsl(h: number, s: number, l: number): this;
|
|
||||||
hsv(h: number, s: number, v: number): this;
|
|
||||||
hwb(h: number, w: number, b: number): this;
|
|
||||||
bgHex(color: string): this;
|
|
||||||
bgKeyword(color: string): this;
|
|
||||||
bgRgb(r: number, g: number, b: number): this;
|
|
||||||
bgHsl(h: number, s: number, l: number): this;
|
|
||||||
bgHsv(h: number, s: number, v: number): this;
|
|
||||||
bgHwb(h: number, w: number, b: number): this;
|
|
||||||
hex(color: string): this;
|
|
||||||
keyword(color: string): this;
|
|
||||||
|
|
||||||
readonly reset: this;
|
|
||||||
readonly bold: this;
|
|
||||||
readonly dim: this;
|
|
||||||
readonly italic: this;
|
|
||||||
readonly underline: this;
|
|
||||||
readonly inverse: this;
|
|
||||||
readonly hidden: this;
|
|
||||||
readonly strikethrough: this;
|
|
||||||
|
|
||||||
readonly visible: this;
|
|
||||||
|
|
||||||
readonly black: this;
|
|
||||||
readonly red: this;
|
|
||||||
readonly green: this;
|
|
||||||
readonly yellow: this;
|
|
||||||
readonly blue: this;
|
|
||||||
readonly magenta: this;
|
|
||||||
readonly cyan: this;
|
|
||||||
readonly white: this;
|
|
||||||
readonly gray: this;
|
|
||||||
readonly grey: this;
|
|
||||||
readonly blackBright: this;
|
|
||||||
readonly redBright: this;
|
|
||||||
readonly greenBright: this;
|
|
||||||
readonly yellowBright: this;
|
|
||||||
readonly blueBright: this;
|
|
||||||
readonly magentaBright: this;
|
|
||||||
readonly cyanBright: this;
|
|
||||||
readonly whiteBright: this;
|
|
||||||
|
|
||||||
readonly bgBlack: this;
|
|
||||||
readonly bgRed: this;
|
|
||||||
readonly bgGreen: this;
|
|
||||||
readonly bgYellow: this;
|
|
||||||
readonly bgBlue: this;
|
|
||||||
readonly bgMagenta: this;
|
|
||||||
readonly bgCyan: this;
|
|
||||||
readonly bgWhite: this;
|
|
||||||
readonly bgBlackBright: this;
|
|
||||||
readonly bgRedBright: this;
|
|
||||||
readonly bgGreenBright: this;
|
|
||||||
readonly bgYellowBright: this;
|
|
||||||
readonly bgBlueBright: this;
|
|
||||||
readonly bgMagentaBright: this;
|
|
||||||
readonly bgCyanBright: this;
|
|
||||||
readonly bgWhiteBright: this;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare const chalk: Chalk & { supportsColor: ColorSupport };
|
|
||||||
|
|
||||||
export default chalk
|
|
|
@ -1,54 +0,0 @@
|
||||||
# 1.0.0 - 2016-01-07
|
|
||||||
|
|
||||||
- Removed: unused speed test
|
|
||||||
- Added: Automatic routing between previously unsupported conversions
|
|
||||||
([#27](https://github.com/Qix-/color-convert/pull/27))
|
|
||||||
- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions
|
|
||||||
([#27](https://github.com/Qix-/color-convert/pull/27))
|
|
||||||
- Removed: `convert()` class
|
|
||||||
([#27](https://github.com/Qix-/color-convert/pull/27))
|
|
||||||
- Changed: all functions to lookup dictionary
|
|
||||||
([#27](https://github.com/Qix-/color-convert/pull/27))
|
|
||||||
- Changed: `ansi` to `ansi256`
|
|
||||||
([#27](https://github.com/Qix-/color-convert/pull/27))
|
|
||||||
- Fixed: argument grouping for functions requiring only one argument
|
|
||||||
([#27](https://github.com/Qix-/color-convert/pull/27))
|
|
||||||
|
|
||||||
# 0.6.0 - 2015-07-23
|
|
||||||
|
|
||||||
- Added: methods to handle
|
|
||||||
[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors:
|
|
||||||
- rgb2ansi16
|
|
||||||
- rgb2ansi
|
|
||||||
- hsl2ansi16
|
|
||||||
- hsl2ansi
|
|
||||||
- hsv2ansi16
|
|
||||||
- hsv2ansi
|
|
||||||
- hwb2ansi16
|
|
||||||
- hwb2ansi
|
|
||||||
- cmyk2ansi16
|
|
||||||
- cmyk2ansi
|
|
||||||
- keyword2ansi16
|
|
||||||
- keyword2ansi
|
|
||||||
- ansi162rgb
|
|
||||||
- ansi162hsl
|
|
||||||
- ansi162hsv
|
|
||||||
- ansi162hwb
|
|
||||||
- ansi162cmyk
|
|
||||||
- ansi162keyword
|
|
||||||
- ansi2rgb
|
|
||||||
- ansi2hsl
|
|
||||||
- ansi2hsv
|
|
||||||
- ansi2hwb
|
|
||||||
- ansi2cmyk
|
|
||||||
- ansi2keyword
|
|
||||||
([#18](https://github.com/harthur/color-convert/pull/18))
|
|
||||||
|
|
||||||
# 0.5.3 - 2015-06-02
|
|
||||||
|
|
||||||
- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]`
|
|
||||||
([#15](https://github.com/harthur/color-convert/issues/15))
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Check out commit logs for older releases
|
|
|
@ -1,21 +0,0 @@
|
||||||
Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
# color-convert
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/Qix-/color-convert.svg?branch=master)](https://travis-ci.org/Qix-/color-convert)
|
|
||||||
|
|
||||||
Color-convert is a color conversion library for JavaScript and node.
|
|
||||||
It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest):
|
|
||||||
|
|
||||||
```js
|
|
||||||
var convert = require('color-convert');
|
|
||||||
|
|
||||||
convert.rgb.hsl(140, 200, 100); // [96, 48, 59]
|
|
||||||
convert.keyword.rgb('blue'); // [0, 0, 255]
|
|
||||||
|
|
||||||
var rgbChannels = convert.rgb.channels; // 3
|
|
||||||
var cmykChannels = convert.cmyk.channels; // 4
|
|
||||||
var ansiChannels = convert.ansi16.channels; // 1
|
|
||||||
```
|
|
||||||
|
|
||||||
# Install
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ npm install color-convert
|
|
||||||
```
|
|
||||||
|
|
||||||
# API
|
|
||||||
|
|
||||||
Simply get the property of the _from_ and _to_ conversion that you're looking for.
|
|
||||||
|
|
||||||
All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function.
|
|
||||||
|
|
||||||
All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha).
|
|
||||||
|
|
||||||
```js
|
|
||||||
var convert = require('color-convert');
|
|
||||||
|
|
||||||
// Hex to LAB
|
|
||||||
convert.hex.lab('DEADBF'); // [ 76, 21, -2 ]
|
|
||||||
convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ]
|
|
||||||
|
|
||||||
// RGB to CMYK
|
|
||||||
convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ]
|
|
||||||
convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Arrays
|
|
||||||
All functions that accept multiple arguments also support passing an array.
|
|
||||||
|
|
||||||
Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.)
|
|
||||||
|
|
||||||
```js
|
|
||||||
var convert = require('color-convert');
|
|
||||||
|
|
||||||
convert.rgb.hex(123, 45, 67); // '7B2D43'
|
|
||||||
convert.rgb.hex([123, 45, 67]); // '7B2D43'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Routing
|
|
||||||
|
|
||||||
Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex).
|
|
||||||
|
|
||||||
Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js).
|
|
||||||
|
|
||||||
# Contribute
|
|
||||||
|
|
||||||
If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request.
|
|
||||||
|
|
||||||
# License
|
|
||||||
Copyright © 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE).
|
|
|
@ -1,868 +0,0 @@
|
||||||
/* MIT license */
|
|
||||||
var cssKeywords = require('color-name');
|
|
||||||
|
|
||||||
// NOTE: conversions should only return primitive values (i.e. arrays, or
|
|
||||||
// values that give correct `typeof` results).
|
|
||||||
// do not use box values types (i.e. Number(), String(), etc.)
|
|
||||||
|
|
||||||
var reverseKeywords = {};
|
|
||||||
for (var key in cssKeywords) {
|
|
||||||
if (cssKeywords.hasOwnProperty(key)) {
|
|
||||||
reverseKeywords[cssKeywords[key]] = key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var convert = module.exports = {
|
|
||||||
rgb: {channels: 3, labels: 'rgb'},
|
|
||||||
hsl: {channels: 3, labels: 'hsl'},
|
|
||||||
hsv: {channels: 3, labels: 'hsv'},
|
|
||||||
hwb: {channels: 3, labels: 'hwb'},
|
|
||||||
cmyk: {channels: 4, labels: 'cmyk'},
|
|
||||||
xyz: {channels: 3, labels: 'xyz'},
|
|
||||||
lab: {channels: 3, labels: 'lab'},
|
|
||||||
lch: {channels: 3, labels: 'lch'},
|
|
||||||
hex: {channels: 1, labels: ['hex']},
|
|
||||||
keyword: {channels: 1, labels: ['keyword']},
|
|
||||||
ansi16: {channels: 1, labels: ['ansi16']},
|
|
||||||
ansi256: {channels: 1, labels: ['ansi256']},
|
|
||||||
hcg: {channels: 3, labels: ['h', 'c', 'g']},
|
|
||||||
apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
|
|
||||||
gray: {channels: 1, labels: ['gray']}
|
|
||||||
};
|
|
||||||
|
|
||||||
// hide .channels and .labels properties
|
|
||||||
for (var model in convert) {
|
|
||||||
if (convert.hasOwnProperty(model)) {
|
|
||||||
if (!('channels' in convert[model])) {
|
|
||||||
throw new Error('missing channels property: ' + model);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!('labels' in convert[model])) {
|
|
||||||
throw new Error('missing channel labels property: ' + model);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (convert[model].labels.length !== convert[model].channels) {
|
|
||||||
throw new Error('channel and label counts mismatch: ' + model);
|
|
||||||
}
|
|
||||||
|
|
||||||
var channels = convert[model].channels;
|
|
||||||
var labels = convert[model].labels;
|
|
||||||
delete convert[model].channels;
|
|
||||||
delete convert[model].labels;
|
|
||||||
Object.defineProperty(convert[model], 'channels', {value: channels});
|
|
||||||
Object.defineProperty(convert[model], 'labels', {value: labels});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
convert.rgb.hsl = function (rgb) {
|
|
||||||
var r = rgb[0] / 255;
|
|
||||||
var g = rgb[1] / 255;
|
|
||||||
var b = rgb[2] / 255;
|
|
||||||
var min = Math.min(r, g, b);
|
|
||||||
var max = Math.max(r, g, b);
|
|
||||||
var delta = max - min;
|
|
||||||
var h;
|
|
||||||
var s;
|
|
||||||
var l;
|
|
||||||
|
|
||||||
if (max === min) {
|
|
||||||
h = 0;
|
|
||||||
} else if (r === max) {
|
|
||||||
h = (g - b) / delta;
|
|
||||||
} else if (g === max) {
|
|
||||||
h = 2 + (b - r) / delta;
|
|
||||||
} else if (b === max) {
|
|
||||||
h = 4 + (r - g) / delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
h = Math.min(h * 60, 360);
|
|
||||||
|
|
||||||
if (h < 0) {
|
|
||||||
h += 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
l = (min + max) / 2;
|
|
||||||
|
|
||||||
if (max === min) {
|
|
||||||
s = 0;
|
|
||||||
} else if (l <= 0.5) {
|
|
||||||
s = delta / (max + min);
|
|
||||||
} else {
|
|
||||||
s = delta / (2 - max - min);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [h, s * 100, l * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.hsv = function (rgb) {
|
|
||||||
var rdif;
|
|
||||||
var gdif;
|
|
||||||
var bdif;
|
|
||||||
var h;
|
|
||||||
var s;
|
|
||||||
|
|
||||||
var r = rgb[0] / 255;
|
|
||||||
var g = rgb[1] / 255;
|
|
||||||
var b = rgb[2] / 255;
|
|
||||||
var v = Math.max(r, g, b);
|
|
||||||
var diff = v - Math.min(r, g, b);
|
|
||||||
var diffc = function (c) {
|
|
||||||
return (v - c) / 6 / diff + 1 / 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (diff === 0) {
|
|
||||||
h = s = 0;
|
|
||||||
} else {
|
|
||||||
s = diff / v;
|
|
||||||
rdif = diffc(r);
|
|
||||||
gdif = diffc(g);
|
|
||||||
bdif = diffc(b);
|
|
||||||
|
|
||||||
if (r === v) {
|
|
||||||
h = bdif - gdif;
|
|
||||||
} else if (g === v) {
|
|
||||||
h = (1 / 3) + rdif - bdif;
|
|
||||||
} else if (b === v) {
|
|
||||||
h = (2 / 3) + gdif - rdif;
|
|
||||||
}
|
|
||||||
if (h < 0) {
|
|
||||||
h += 1;
|
|
||||||
} else if (h > 1) {
|
|
||||||
h -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
h * 360,
|
|
||||||
s * 100,
|
|
||||||
v * 100
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.hwb = function (rgb) {
|
|
||||||
var r = rgb[0];
|
|
||||||
var g = rgb[1];
|
|
||||||
var b = rgb[2];
|
|
||||||
var h = convert.rgb.hsl(rgb)[0];
|
|
||||||
var w = 1 / 255 * Math.min(r, Math.min(g, b));
|
|
||||||
|
|
||||||
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
|
|
||||||
|
|
||||||
return [h, w * 100, b * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.cmyk = function (rgb) {
|
|
||||||
var r = rgb[0] / 255;
|
|
||||||
var g = rgb[1] / 255;
|
|
||||||
var b = rgb[2] / 255;
|
|
||||||
var c;
|
|
||||||
var m;
|
|
||||||
var y;
|
|
||||||
var k;
|
|
||||||
|
|
||||||
k = Math.min(1 - r, 1 - g, 1 - b);
|
|
||||||
c = (1 - r - k) / (1 - k) || 0;
|
|
||||||
m = (1 - g - k) / (1 - k) || 0;
|
|
||||||
y = (1 - b - k) / (1 - k) || 0;
|
|
||||||
|
|
||||||
return [c * 100, m * 100, y * 100, k * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
|
|
||||||
* */
|
|
||||||
function comparativeDistance(x, y) {
|
|
||||||
return (
|
|
||||||
Math.pow(x[0] - y[0], 2) +
|
|
||||||
Math.pow(x[1] - y[1], 2) +
|
|
||||||
Math.pow(x[2] - y[2], 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
convert.rgb.keyword = function (rgb) {
|
|
||||||
var reversed = reverseKeywords[rgb];
|
|
||||||
if (reversed) {
|
|
||||||
return reversed;
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentClosestDistance = Infinity;
|
|
||||||
var currentClosestKeyword;
|
|
||||||
|
|
||||||
for (var keyword in cssKeywords) {
|
|
||||||
if (cssKeywords.hasOwnProperty(keyword)) {
|
|
||||||
var value = cssKeywords[keyword];
|
|
||||||
|
|
||||||
// Compute comparative distance
|
|
||||||
var distance = comparativeDistance(rgb, value);
|
|
||||||
|
|
||||||
// Check if its less, if so set as closest
|
|
||||||
if (distance < currentClosestDistance) {
|
|
||||||
currentClosestDistance = distance;
|
|
||||||
currentClosestKeyword = keyword;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentClosestKeyword;
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.keyword.rgb = function (keyword) {
|
|
||||||
return cssKeywords[keyword];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.xyz = function (rgb) {
|
|
||||||
var r = rgb[0] / 255;
|
|
||||||
var g = rgb[1] / 255;
|
|
||||||
var b = rgb[2] / 255;
|
|
||||||
|
|
||||||
// assume sRGB
|
|
||||||
r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
|
|
||||||
g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
|
|
||||||
b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
|
|
||||||
|
|
||||||
var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
|
|
||||||
var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
|
|
||||||
var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
|
|
||||||
|
|
||||||
return [x * 100, y * 100, z * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.lab = function (rgb) {
|
|
||||||
var xyz = convert.rgb.xyz(rgb);
|
|
||||||
var x = xyz[0];
|
|
||||||
var y = xyz[1];
|
|
||||||
var z = xyz[2];
|
|
||||||
var l;
|
|
||||||
var a;
|
|
||||||
var b;
|
|
||||||
|
|
||||||
x /= 95.047;
|
|
||||||
y /= 100;
|
|
||||||
z /= 108.883;
|
|
||||||
|
|
||||||
x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
|
|
||||||
y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
|
|
||||||
z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
|
|
||||||
|
|
||||||
l = (116 * y) - 16;
|
|
||||||
a = 500 * (x - y);
|
|
||||||
b = 200 * (y - z);
|
|
||||||
|
|
||||||
return [l, a, b];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hsl.rgb = function (hsl) {
|
|
||||||
var h = hsl[0] / 360;
|
|
||||||
var s = hsl[1] / 100;
|
|
||||||
var l = hsl[2] / 100;
|
|
||||||
var t1;
|
|
||||||
var t2;
|
|
||||||
var t3;
|
|
||||||
var rgb;
|
|
||||||
var val;
|
|
||||||
|
|
||||||
if (s === 0) {
|
|
||||||
val = l * 255;
|
|
||||||
return [val, val, val];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l < 0.5) {
|
|
||||||
t2 = l * (1 + s);
|
|
||||||
} else {
|
|
||||||
t2 = l + s - l * s;
|
|
||||||
}
|
|
||||||
|
|
||||||
t1 = 2 * l - t2;
|
|
||||||
|
|
||||||
rgb = [0, 0, 0];
|
|
||||||
for (var i = 0; i < 3; i++) {
|
|
||||||
t3 = h + 1 / 3 * -(i - 1);
|
|
||||||
if (t3 < 0) {
|
|
||||||
t3++;
|
|
||||||
}
|
|
||||||
if (t3 > 1) {
|
|
||||||
t3--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (6 * t3 < 1) {
|
|
||||||
val = t1 + (t2 - t1) * 6 * t3;
|
|
||||||
} else if (2 * t3 < 1) {
|
|
||||||
val = t2;
|
|
||||||
} else if (3 * t3 < 2) {
|
|
||||||
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
|
|
||||||
} else {
|
|
||||||
val = t1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rgb[i] = val * 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rgb;
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hsl.hsv = function (hsl) {
|
|
||||||
var h = hsl[0];
|
|
||||||
var s = hsl[1] / 100;
|
|
||||||
var l = hsl[2] / 100;
|
|
||||||
var smin = s;
|
|
||||||
var lmin = Math.max(l, 0.01);
|
|
||||||
var sv;
|
|
||||||
var v;
|
|
||||||
|
|
||||||
l *= 2;
|
|
||||||
s *= (l <= 1) ? l : 2 - l;
|
|
||||||
smin *= lmin <= 1 ? lmin : 2 - lmin;
|
|
||||||
v = (l + s) / 2;
|
|
||||||
sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
|
|
||||||
|
|
||||||
return [h, sv * 100, v * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hsv.rgb = function (hsv) {
|
|
||||||
var h = hsv[0] / 60;
|
|
||||||
var s = hsv[1] / 100;
|
|
||||||
var v = hsv[2] / 100;
|
|
||||||
var hi = Math.floor(h) % 6;
|
|
||||||
|
|
||||||
var f = h - Math.floor(h);
|
|
||||||
var p = 255 * v * (1 - s);
|
|
||||||
var q = 255 * v * (1 - (s * f));
|
|
||||||
var t = 255 * v * (1 - (s * (1 - f)));
|
|
||||||
v *= 255;
|
|
||||||
|
|
||||||
switch (hi) {
|
|
||||||
case 0:
|
|
||||||
return [v, t, p];
|
|
||||||
case 1:
|
|
||||||
return [q, v, p];
|
|
||||||
case 2:
|
|
||||||
return [p, v, t];
|
|
||||||
case 3:
|
|
||||||
return [p, q, v];
|
|
||||||
case 4:
|
|
||||||
return [t, p, v];
|
|
||||||
case 5:
|
|
||||||
return [v, p, q];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hsv.hsl = function (hsv) {
|
|
||||||
var h = hsv[0];
|
|
||||||
var s = hsv[1] / 100;
|
|
||||||
var v = hsv[2] / 100;
|
|
||||||
var vmin = Math.max(v, 0.01);
|
|
||||||
var lmin;
|
|
||||||
var sl;
|
|
||||||
var l;
|
|
||||||
|
|
||||||
l = (2 - s) * v;
|
|
||||||
lmin = (2 - s) * vmin;
|
|
||||||
sl = s * vmin;
|
|
||||||
sl /= (lmin <= 1) ? lmin : 2 - lmin;
|
|
||||||
sl = sl || 0;
|
|
||||||
l /= 2;
|
|
||||||
|
|
||||||
return [h, sl * 100, l * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
|
|
||||||
convert.hwb.rgb = function (hwb) {
|
|
||||||
var h = hwb[0] / 360;
|
|
||||||
var wh = hwb[1] / 100;
|
|
||||||
var bl = hwb[2] / 100;
|
|
||||||
var ratio = wh + bl;
|
|
||||||
var i;
|
|
||||||
var v;
|
|
||||||
var f;
|
|
||||||
var n;
|
|
||||||
|
|
||||||
// wh + bl cant be > 1
|
|
||||||
if (ratio > 1) {
|
|
||||||
wh /= ratio;
|
|
||||||
bl /= ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = Math.floor(6 * h);
|
|
||||||
v = 1 - bl;
|
|
||||||
f = 6 * h - i;
|
|
||||||
|
|
||||||
if ((i & 0x01) !== 0) {
|
|
||||||
f = 1 - f;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = wh + f * (v - wh); // linear interpolation
|
|
||||||
|
|
||||||
var r;
|
|
||||||
var g;
|
|
||||||
var b;
|
|
||||||
switch (i) {
|
|
||||||
default:
|
|
||||||
case 6:
|
|
||||||
case 0: r = v; g = n; b = wh; break;
|
|
||||||
case 1: r = n; g = v; b = wh; break;
|
|
||||||
case 2: r = wh; g = v; b = n; break;
|
|
||||||
case 3: r = wh; g = n; b = v; break;
|
|
||||||
case 4: r = n; g = wh; b = v; break;
|
|
||||||
case 5: r = v; g = wh; b = n; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [r * 255, g * 255, b * 255];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.cmyk.rgb = function (cmyk) {
|
|
||||||
var c = cmyk[0] / 100;
|
|
||||||
var m = cmyk[1] / 100;
|
|
||||||
var y = cmyk[2] / 100;
|
|
||||||
var k = cmyk[3] / 100;
|
|
||||||
var r;
|
|
||||||
var g;
|
|
||||||
var b;
|
|
||||||
|
|
||||||
r = 1 - Math.min(1, c * (1 - k) + k);
|
|
||||||
g = 1 - Math.min(1, m * (1 - k) + k);
|
|
||||||
b = 1 - Math.min(1, y * (1 - k) + k);
|
|
||||||
|
|
||||||
return [r * 255, g * 255, b * 255];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.xyz.rgb = function (xyz) {
|
|
||||||
var x = xyz[0] / 100;
|
|
||||||
var y = xyz[1] / 100;
|
|
||||||
var z = xyz[2] / 100;
|
|
||||||
var r;
|
|
||||||
var g;
|
|
||||||
var b;
|
|
||||||
|
|
||||||
r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
|
|
||||||
g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
|
|
||||||
b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
|
|
||||||
|
|
||||||
// assume sRGB
|
|
||||||
r = r > 0.0031308
|
|
||||||
? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
|
|
||||||
: r * 12.92;
|
|
||||||
|
|
||||||
g = g > 0.0031308
|
|
||||||
? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
|
|
||||||
: g * 12.92;
|
|
||||||
|
|
||||||
b = b > 0.0031308
|
|
||||||
? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
|
|
||||||
: b * 12.92;
|
|
||||||
|
|
||||||
r = Math.min(Math.max(0, r), 1);
|
|
||||||
g = Math.min(Math.max(0, g), 1);
|
|
||||||
b = Math.min(Math.max(0, b), 1);
|
|
||||||
|
|
||||||
return [r * 255, g * 255, b * 255];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.xyz.lab = function (xyz) {
|
|
||||||
var x = xyz[0];
|
|
||||||
var y = xyz[1];
|
|
||||||
var z = xyz[2];
|
|
||||||
var l;
|
|
||||||
var a;
|
|
||||||
var b;
|
|
||||||
|
|
||||||
x /= 95.047;
|
|
||||||
y /= 100;
|
|
||||||
z /= 108.883;
|
|
||||||
|
|
||||||
x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
|
|
||||||
y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
|
|
||||||
z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
|
|
||||||
|
|
||||||
l = (116 * y) - 16;
|
|
||||||
a = 500 * (x - y);
|
|
||||||
b = 200 * (y - z);
|
|
||||||
|
|
||||||
return [l, a, b];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.lab.xyz = function (lab) {
|
|
||||||
var l = lab[0];
|
|
||||||
var a = lab[1];
|
|
||||||
var b = lab[2];
|
|
||||||
var x;
|
|
||||||
var y;
|
|
||||||
var z;
|
|
||||||
|
|
||||||
y = (l + 16) / 116;
|
|
||||||
x = a / 500 + y;
|
|
||||||
z = y - b / 200;
|
|
||||||
|
|
||||||
var y2 = Math.pow(y, 3);
|
|
||||||
var x2 = Math.pow(x, 3);
|
|
||||||
var z2 = Math.pow(z, 3);
|
|
||||||
y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
|
|
||||||
x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
|
|
||||||
z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
|
|
||||||
|
|
||||||
x *= 95.047;
|
|
||||||
y *= 100;
|
|
||||||
z *= 108.883;
|
|
||||||
|
|
||||||
return [x, y, z];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.lab.lch = function (lab) {
|
|
||||||
var l = lab[0];
|
|
||||||
var a = lab[1];
|
|
||||||
var b = lab[2];
|
|
||||||
var hr;
|
|
||||||
var h;
|
|
||||||
var c;
|
|
||||||
|
|
||||||
hr = Math.atan2(b, a);
|
|
||||||
h = hr * 360 / 2 / Math.PI;
|
|
||||||
|
|
||||||
if (h < 0) {
|
|
||||||
h += 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = Math.sqrt(a * a + b * b);
|
|
||||||
|
|
||||||
return [l, c, h];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.lch.lab = function (lch) {
|
|
||||||
var l = lch[0];
|
|
||||||
var c = lch[1];
|
|
||||||
var h = lch[2];
|
|
||||||
var a;
|
|
||||||
var b;
|
|
||||||
var hr;
|
|
||||||
|
|
||||||
hr = h / 360 * 2 * Math.PI;
|
|
||||||
a = c * Math.cos(hr);
|
|
||||||
b = c * Math.sin(hr);
|
|
||||||
|
|
||||||
return [l, a, b];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.ansi16 = function (args) {
|
|
||||||
var r = args[0];
|
|
||||||
var g = args[1];
|
|
||||||
var b = args[2];
|
|
||||||
var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization
|
|
||||||
|
|
||||||
value = Math.round(value / 50);
|
|
||||||
|
|
||||||
if (value === 0) {
|
|
||||||
return 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ansi = 30
|
|
||||||
+ ((Math.round(b / 255) << 2)
|
|
||||||
| (Math.round(g / 255) << 1)
|
|
||||||
| Math.round(r / 255));
|
|
||||||
|
|
||||||
if (value === 2) {
|
|
||||||
ansi += 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ansi;
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hsv.ansi16 = function (args) {
|
|
||||||
// optimization here; we already know the value and don't need to get
|
|
||||||
// it converted for us.
|
|
||||||
return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.ansi256 = function (args) {
|
|
||||||
var r = args[0];
|
|
||||||
var g = args[1];
|
|
||||||
var b = args[2];
|
|
||||||
|
|
||||||
// we use the extended greyscale palette here, with the exception of
|
|
||||||
// black and white. normal palette only has 4 greyscale shades.
|
|
||||||
if (r === g && g === b) {
|
|
||||||
if (r < 8) {
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r > 248) {
|
|
||||||
return 231;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.round(((r - 8) / 247) * 24) + 232;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ansi = 16
|
|
||||||
+ (36 * Math.round(r / 255 * 5))
|
|
||||||
+ (6 * Math.round(g / 255 * 5))
|
|
||||||
+ Math.round(b / 255 * 5);
|
|
||||||
|
|
||||||
return ansi;
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.ansi16.rgb = function (args) {
|
|
||||||
var color = args % 10;
|
|
||||||
|
|
||||||
// handle greyscale
|
|
||||||
if (color === 0 || color === 7) {
|
|
||||||
if (args > 50) {
|
|
||||||
color += 3.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
color = color / 10.5 * 255;
|
|
||||||
|
|
||||||
return [color, color, color];
|
|
||||||
}
|
|
||||||
|
|
||||||
var mult = (~~(args > 50) + 1) * 0.5;
|
|
||||||
var r = ((color & 1) * mult) * 255;
|
|
||||||
var g = (((color >> 1) & 1) * mult) * 255;
|
|
||||||
var b = (((color >> 2) & 1) * mult) * 255;
|
|
||||||
|
|
||||||
return [r, g, b];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.ansi256.rgb = function (args) {
|
|
||||||
// handle greyscale
|
|
||||||
if (args >= 232) {
|
|
||||||
var c = (args - 232) * 10 + 8;
|
|
||||||
return [c, c, c];
|
|
||||||
}
|
|
||||||
|
|
||||||
args -= 16;
|
|
||||||
|
|
||||||
var rem;
|
|
||||||
var r = Math.floor(args / 36) / 5 * 255;
|
|
||||||
var g = Math.floor((rem = args % 36) / 6) / 5 * 255;
|
|
||||||
var b = (rem % 6) / 5 * 255;
|
|
||||||
|
|
||||||
return [r, g, b];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.hex = function (args) {
|
|
||||||
var integer = ((Math.round(args[0]) & 0xFF) << 16)
|
|
||||||
+ ((Math.round(args[1]) & 0xFF) << 8)
|
|
||||||
+ (Math.round(args[2]) & 0xFF);
|
|
||||||
|
|
||||||
var string = integer.toString(16).toUpperCase();
|
|
||||||
return '000000'.substring(string.length) + string;
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hex.rgb = function (args) {
|
|
||||||
var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
|
|
||||||
if (!match) {
|
|
||||||
return [0, 0, 0];
|
|
||||||
}
|
|
||||||
|
|
||||||
var colorString = match[0];
|
|
||||||
|
|
||||||
if (match[0].length === 3) {
|
|
||||||
colorString = colorString.split('').map(function (char) {
|
|
||||||
return char + char;
|
|
||||||
}).join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
var integer = parseInt(colorString, 16);
|
|
||||||
var r = (integer >> 16) & 0xFF;
|
|
||||||
var g = (integer >> 8) & 0xFF;
|
|
||||||
var b = integer & 0xFF;
|
|
||||||
|
|
||||||
return [r, g, b];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.hcg = function (rgb) {
|
|
||||||
var r = rgb[0] / 255;
|
|
||||||
var g = rgb[1] / 255;
|
|
||||||
var b = rgb[2] / 255;
|
|
||||||
var max = Math.max(Math.max(r, g), b);
|
|
||||||
var min = Math.min(Math.min(r, g), b);
|
|
||||||
var chroma = (max - min);
|
|
||||||
var grayscale;
|
|
||||||
var hue;
|
|
||||||
|
|
||||||
if (chroma < 1) {
|
|
||||||
grayscale = min / (1 - chroma);
|
|
||||||
} else {
|
|
||||||
grayscale = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chroma <= 0) {
|
|
||||||
hue = 0;
|
|
||||||
} else
|
|
||||||
if (max === r) {
|
|
||||||
hue = ((g - b) / chroma) % 6;
|
|
||||||
} else
|
|
||||||
if (max === g) {
|
|
||||||
hue = 2 + (b - r) / chroma;
|
|
||||||
} else {
|
|
||||||
hue = 4 + (r - g) / chroma + 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
hue /= 6;
|
|
||||||
hue %= 1;
|
|
||||||
|
|
||||||
return [hue * 360, chroma * 100, grayscale * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hsl.hcg = function (hsl) {
|
|
||||||
var s = hsl[1] / 100;
|
|
||||||
var l = hsl[2] / 100;
|
|
||||||
var c = 1;
|
|
||||||
var f = 0;
|
|
||||||
|
|
||||||
if (l < 0.5) {
|
|
||||||
c = 2.0 * s * l;
|
|
||||||
} else {
|
|
||||||
c = 2.0 * s * (1.0 - l);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c < 1.0) {
|
|
||||||
f = (l - 0.5 * c) / (1.0 - c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [hsl[0], c * 100, f * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hsv.hcg = function (hsv) {
|
|
||||||
var s = hsv[1] / 100;
|
|
||||||
var v = hsv[2] / 100;
|
|
||||||
|
|
||||||
var c = s * v;
|
|
||||||
var f = 0;
|
|
||||||
|
|
||||||
if (c < 1.0) {
|
|
||||||
f = (v - c) / (1 - c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [hsv[0], c * 100, f * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hcg.rgb = function (hcg) {
|
|
||||||
var h = hcg[0] / 360;
|
|
||||||
var c = hcg[1] / 100;
|
|
||||||
var g = hcg[2] / 100;
|
|
||||||
|
|
||||||
if (c === 0.0) {
|
|
||||||
return [g * 255, g * 255, g * 255];
|
|
||||||
}
|
|
||||||
|
|
||||||
var pure = [0, 0, 0];
|
|
||||||
var hi = (h % 1) * 6;
|
|
||||||
var v = hi % 1;
|
|
||||||
var w = 1 - v;
|
|
||||||
var mg = 0;
|
|
||||||
|
|
||||||
switch (Math.floor(hi)) {
|
|
||||||
case 0:
|
|
||||||
pure[0] = 1; pure[1] = v; pure[2] = 0; break;
|
|
||||||
case 1:
|
|
||||||
pure[0] = w; pure[1] = 1; pure[2] = 0; break;
|
|
||||||
case 2:
|
|
||||||
pure[0] = 0; pure[1] = 1; pure[2] = v; break;
|
|
||||||
case 3:
|
|
||||||
pure[0] = 0; pure[1] = w; pure[2] = 1; break;
|
|
||||||
case 4:
|
|
||||||
pure[0] = v; pure[1] = 0; pure[2] = 1; break;
|
|
||||||
default:
|
|
||||||
pure[0] = 1; pure[1] = 0; pure[2] = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
mg = (1.0 - c) * g;
|
|
||||||
|
|
||||||
return [
|
|
||||||
(c * pure[0] + mg) * 255,
|
|
||||||
(c * pure[1] + mg) * 255,
|
|
||||||
(c * pure[2] + mg) * 255
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hcg.hsv = function (hcg) {
|
|
||||||
var c = hcg[1] / 100;
|
|
||||||
var g = hcg[2] / 100;
|
|
||||||
|
|
||||||
var v = c + g * (1.0 - c);
|
|
||||||
var f = 0;
|
|
||||||
|
|
||||||
if (v > 0.0) {
|
|
||||||
f = c / v;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [hcg[0], f * 100, v * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hcg.hsl = function (hcg) {
|
|
||||||
var c = hcg[1] / 100;
|
|
||||||
var g = hcg[2] / 100;
|
|
||||||
|
|
||||||
var l = g * (1.0 - c) + 0.5 * c;
|
|
||||||
var s = 0;
|
|
||||||
|
|
||||||
if (l > 0.0 && l < 0.5) {
|
|
||||||
s = c / (2 * l);
|
|
||||||
} else
|
|
||||||
if (l >= 0.5 && l < 1.0) {
|
|
||||||
s = c / (2 * (1 - l));
|
|
||||||
}
|
|
||||||
|
|
||||||
return [hcg[0], s * 100, l * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hcg.hwb = function (hcg) {
|
|
||||||
var c = hcg[1] / 100;
|
|
||||||
var g = hcg[2] / 100;
|
|
||||||
var v = c + g * (1.0 - c);
|
|
||||||
return [hcg[0], (v - c) * 100, (1 - v) * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.hwb.hcg = function (hwb) {
|
|
||||||
var w = hwb[1] / 100;
|
|
||||||
var b = hwb[2] / 100;
|
|
||||||
var v = 1 - b;
|
|
||||||
var c = v - w;
|
|
||||||
var g = 0;
|
|
||||||
|
|
||||||
if (c < 1) {
|
|
||||||
g = (v - c) / (1 - c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [hwb[0], c * 100, g * 100];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.apple.rgb = function (apple) {
|
|
||||||
return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.apple = function (rgb) {
|
|
||||||
return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.gray.rgb = function (args) {
|
|
||||||
return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.gray.hsl = convert.gray.hsv = function (args) {
|
|
||||||
return [0, 0, args[0]];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.gray.hwb = function (gray) {
|
|
||||||
return [0, 100, gray[0]];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.gray.cmyk = function (gray) {
|
|
||||||
return [0, 0, 0, gray[0]];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.gray.lab = function (gray) {
|
|
||||||
return [gray[0], 0, 0];
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.gray.hex = function (gray) {
|
|
||||||
var val = Math.round(gray[0] / 100 * 255) & 0xFF;
|
|
||||||
var integer = (val << 16) + (val << 8) + val;
|
|
||||||
|
|
||||||
var string = integer.toString(16).toUpperCase();
|
|
||||||
return '000000'.substring(string.length) + string;
|
|
||||||
};
|
|
||||||
|
|
||||||
convert.rgb.gray = function (rgb) {
|
|
||||||
var val = (rgb[0] + rgb[1] + rgb[2]) / 3;
|
|
||||||
return [val / 255 * 100];
|
|
||||||
};
|
|
|
@ -1,78 +0,0 @@
|
||||||
var conversions = require('./conversions');
|
|
||||||
var route = require('./route');
|
|
||||||
|
|
||||||
var convert = {};
|
|
||||||
|
|
||||||
var models = Object.keys(conversions);
|
|
||||||
|
|
||||||
function wrapRaw(fn) {
|
|
||||||
var wrappedFn = function (args) {
|
|
||||||
if (args === undefined || args === null) {
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arguments.length > 1) {
|
|
||||||
args = Array.prototype.slice.call(arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fn(args);
|
|
||||||
};
|
|
||||||
|
|
||||||
// preserve .conversion property if there is one
|
|
||||||
if ('conversion' in fn) {
|
|
||||||
wrappedFn.conversion = fn.conversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrappedFn;
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrapRounded(fn) {
|
|
||||||
var wrappedFn = function (args) {
|
|
||||||
if (args === undefined || args === null) {
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arguments.length > 1) {
|
|
||||||
args = Array.prototype.slice.call(arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = fn(args);
|
|
||||||
|
|
||||||
// we're assuming the result is an array here.
|
|
||||||
// see notice in conversions.js; don't use box types
|
|
||||||
// in conversion functions.
|
|
||||||
if (typeof result === 'object') {
|
|
||||||
for (var len = result.length, i = 0; i < len; i++) {
|
|
||||||
result[i] = Math.round(result[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// preserve .conversion property if there is one
|
|
||||||
if ('conversion' in fn) {
|
|
||||||
wrappedFn.conversion = fn.conversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrappedFn;
|
|
||||||
}
|
|
||||||
|
|
||||||
models.forEach(function (fromModel) {
|
|
||||||
convert[fromModel] = {};
|
|
||||||
|
|
||||||
Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
|
|
||||||
Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
|
|
||||||
|
|
||||||
var routes = route(fromModel);
|
|
||||||
var routeModels = Object.keys(routes);
|
|
||||||
|
|
||||||
routeModels.forEach(function (toModel) {
|
|
||||||
var fn = routes[toModel];
|
|
||||||
|
|
||||||
convert[fromModel][toModel] = wrapRounded(fn);
|
|
||||||
convert[fromModel][toModel].raw = wrapRaw(fn);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = convert;
|
|
|
@ -1,46 +0,0 @@
|
||||||
{
|
|
||||||
"name": "color-convert",
|
|
||||||
"description": "Plain color conversion functions",
|
|
||||||
"version": "1.9.3",
|
|
||||||
"author": "Heather Arthur <fayearthur@gmail.com>",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": "Qix-/color-convert",
|
|
||||||
"scripts": {
|
|
||||||
"pretest": "xo",
|
|
||||||
"test": "node test/basic.js"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"color",
|
|
||||||
"colour",
|
|
||||||
"convert",
|
|
||||||
"converter",
|
|
||||||
"conversion",
|
|
||||||
"rgb",
|
|
||||||
"hsl",
|
|
||||||
"hsv",
|
|
||||||
"hwb",
|
|
||||||
"cmyk",
|
|
||||||
"ansi",
|
|
||||||
"ansi16"
|
|
||||||
],
|
|
||||||
"files": [
|
|
||||||
"index.js",
|
|
||||||
"conversions.js",
|
|
||||||
"css-keywords.js",
|
|
||||||
"route.js"
|
|
||||||
],
|
|
||||||
"xo": {
|
|
||||||
"rules": {
|
|
||||||
"default-case": 0,
|
|
||||||
"no-inline-comments": 0,
|
|
||||||
"operator-linebreak": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"chalk": "1.1.1",
|
|
||||||
"xo": "0.11.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"color-name": "1.1.3"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
var conversions = require('./conversions');
|
|
||||||
|
|
||||||
/*
|
|
||||||
this function routes a model to all other models.
|
|
||||||
|
|
||||||
all functions that are routed have a property `.conversion` attached
|
|
||||||
to the returned synthetic function. This property is an array
|
|
||||||
of strings, each with the steps in between the 'from' and 'to'
|
|
||||||
color models (inclusive).
|
|
||||||
|
|
||||||
conversions that are not possible simply are not included.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function buildGraph() {
|
|
||||||
var graph = {};
|
|
||||||
// https://jsperf.com/object-keys-vs-for-in-with-closure/3
|
|
||||||
var models = Object.keys(conversions);
|
|
||||||
|
|
||||||
for (var len = models.length, i = 0; i < len; i++) {
|
|
||||||
graph[models[i]] = {
|
|
||||||
// http://jsperf.com/1-vs-infinity
|
|
||||||
// micro-opt, but this is simple.
|
|
||||||
distance: -1,
|
|
||||||
parent: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Breadth-first_search
|
|
||||||
function deriveBFS(fromModel) {
|
|
||||||
var graph = buildGraph();
|
|
||||||
var queue = [fromModel]; // unshift -> queue -> pop
|
|
||||||
|
|
||||||
graph[fromModel].distance = 0;
|
|
||||||
|
|
||||||
while (queue.length) {
|
|
||||||
var current = queue.pop();
|
|
||||||
var adjacents = Object.keys(conversions[current]);
|
|
||||||
|
|
||||||
for (var len = adjacents.length, i = 0; i < len; i++) {
|
|
||||||
var adjacent = adjacents[i];
|
|
||||||
var node = graph[adjacent];
|
|
||||||
|
|
||||||
if (node.distance === -1) {
|
|
||||||
node.distance = graph[current].distance + 1;
|
|
||||||
node.parent = current;
|
|
||||||
queue.unshift(adjacent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
function link(from, to) {
|
|
||||||
return function (args) {
|
|
||||||
return to(from(args));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrapConversion(toModel, graph) {
|
|
||||||
var path = [graph[toModel].parent, toModel];
|
|
||||||
var fn = conversions[graph[toModel].parent][toModel];
|
|
||||||
|
|
||||||
var cur = graph[toModel].parent;
|
|
||||||
while (graph[cur].parent) {
|
|
||||||
path.unshift(graph[cur].parent);
|
|
||||||
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
||||||
cur = graph[cur].parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn.conversion = path;
|
|
||||||
return fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function (fromModel) {
|
|
||||||
var graph = deriveBFS(fromModel);
|
|
||||||
var conversion = {};
|
|
||||||
|
|
||||||
var models = Object.keys(graph);
|
|
||||||
for (var len = models.length, i = 0; i < len; i++) {
|
|
||||||
var toModel = models[i];
|
|
||||||
var node = graph[toModel];
|
|
||||||
|
|
||||||
if (node.parent === null) {
|
|
||||||
// no possible conversion, or this node is the source model.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
conversion[toModel] = wrapConversion(toModel, graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
return conversion;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"node": true,
|
|
||||||
"commonjs": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"rules": {
|
|
||||||
"strict": 2,
|
|
||||||
"indent": 0,
|
|
||||||
"linebreak-style": 0,
|
|
||||||
"quotes": 0,
|
|
||||||
"semi": 0,
|
|
||||||
"no-cond-assign": 1,
|
|
||||||
"no-constant-condition": 1,
|
|
||||||
"no-duplicate-case": 1,
|
|
||||||
"no-empty": 1,
|
|
||||||
"no-ex-assign": 1,
|
|
||||||
"no-extra-boolean-cast": 1,
|
|
||||||
"no-extra-semi": 1,
|
|
||||||
"no-fallthrough": 1,
|
|
||||||
"no-func-assign": 1,
|
|
||||||
"no-global-assign": 1,
|
|
||||||
"no-implicit-globals": 2,
|
|
||||||
"no-inner-declarations": ["error", "functions"],
|
|
||||||
"no-irregular-whitespace": 2,
|
|
||||||
"no-loop-func": 1,
|
|
||||||
"no-multi-str": 1,
|
|
||||||
"no-mixed-spaces-and-tabs": 1,
|
|
||||||
"no-proto": 1,
|
|
||||||
"no-sequences": 1,
|
|
||||||
"no-throw-literal": 1,
|
|
||||||
"no-unmodified-loop-condition": 1,
|
|
||||||
"no-useless-call": 1,
|
|
||||||
"no-void": 1,
|
|
||||||
"no-with": 2,
|
|
||||||
"wrap-iife": 1,
|
|
||||||
"no-redeclare": 1,
|
|
||||||
"no-unused-vars": ["error", { "vars": "all", "args": "none" }],
|
|
||||||
"no-sparse-arrays": 1
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
//this will affect all the git repos
|
|
||||||
git config --global core.excludesfile ~/.gitignore
|
|
||||||
|
|
||||||
|
|
||||||
//update files since .ignore won't if already tracked
|
|
||||||
git rm --cached <file>
|
|
||||||
|
|
||||||
# Compiled source #
|
|
||||||
###################
|
|
||||||
*.com
|
|
||||||
*.class
|
|
||||||
*.dll
|
|
||||||
*.exe
|
|
||||||
*.o
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Packages #
|
|
||||||
############
|
|
||||||
# it's better to unpack these files and commit the raw source
|
|
||||||
# git has its own built in compression methods
|
|
||||||
*.7z
|
|
||||||
*.dmg
|
|
||||||
*.gz
|
|
||||||
*.iso
|
|
||||||
*.jar
|
|
||||||
*.rar
|
|
||||||
*.tar
|
|
||||||
*.zip
|
|
||||||
|
|
||||||
# Logs and databases #
|
|
||||||
######################
|
|
||||||
*.log
|
|
||||||
*.sql
|
|
||||||
*.sqlite
|
|
||||||
|
|
||||||
# OS generated files #
|
|
||||||
######################
|
|
||||||
.DS_Store
|
|
||||||
.DS_Store?
|
|
||||||
._*
|
|
||||||
.Spotlight-V100
|
|
||||||
.Trashes
|
|
||||||
# Icon?
|
|
||||||
ehthumbs.db
|
|
||||||
Thumbs.db
|
|
||||||
.cache
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.tmproj
|
|
||||||
*.esproj
|
|
||||||
nbproject
|
|
||||||
|
|
||||||
# Numerous always-ignore extensions #
|
|
||||||
#####################################
|
|
||||||
*.diff
|
|
||||||
*.err
|
|
||||||
*.orig
|
|
||||||
*.rej
|
|
||||||
*.swn
|
|
||||||
*.swo
|
|
||||||
*.swp
|
|
||||||
*.vi
|
|
||||||
*~
|
|
||||||
*.sass-cache
|
|
||||||
*.grunt
|
|
||||||
*.tmp
|
|
||||||
|
|
||||||
# Dreamweaver added files #
|
|
||||||
###########################
|
|
||||||
_notes
|
|
||||||
dwsync.xml
|
|
||||||
|
|
||||||
# Komodo #
|
|
||||||
###########################
|
|
||||||
*.komodoproject
|
|
||||||
.komodotools
|
|
||||||
|
|
||||||
# Node #
|
|
||||||
#####################
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
# Bower #
|
|
||||||
#####################
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# Folders to ignore #
|
|
||||||
#####################
|
|
||||||
.hg
|
|
||||||
.svn
|
|
||||||
.CVS
|
|
||||||
intermediate
|
|
||||||
publish
|
|
||||||
.idea
|
|
||||||
.graphics
|
|
||||||
_test
|
|
||||||
_archive
|
|
||||||
uploads
|
|
||||||
tmp
|
|
||||||
|
|
||||||
# Vim files to ignore #
|
|
||||||
#######################
|
|
||||||
.VimballRecord
|
|
||||||
.netrwhist
|
|
||||||
|
|
||||||
bundle.*
|
|
||||||
|
|
||||||
_demo
|
|
|
@ -1,8 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
Copyright (c) 2015 Dmitry Ivanov
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,11 +0,0 @@
|
||||||
A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.
|
|
||||||
|
|
||||||
[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/)
|
|
||||||
|
|
||||||
|
|
||||||
```js
|
|
||||||
var colors = require('color-name');
|
|
||||||
colors.red //[255,0,0]
|
|
||||||
```
|
|
||||||
|
|
||||||
<a href="LICENSE"><img src="https://upload.wikimedia.org/wikipedia/commons/0/0c/MIT_logo.svg" width="120"/></a>
|
|
|
@ -1,152 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
"aliceblue": [240, 248, 255],
|
|
||||||
"antiquewhite": [250, 235, 215],
|
|
||||||
"aqua": [0, 255, 255],
|
|
||||||
"aquamarine": [127, 255, 212],
|
|
||||||
"azure": [240, 255, 255],
|
|
||||||
"beige": [245, 245, 220],
|
|
||||||
"bisque": [255, 228, 196],
|
|
||||||
"black": [0, 0, 0],
|
|
||||||
"blanchedalmond": [255, 235, 205],
|
|
||||||
"blue": [0, 0, 255],
|
|
||||||
"blueviolet": [138, 43, 226],
|
|
||||||
"brown": [165, 42, 42],
|
|
||||||
"burlywood": [222, 184, 135],
|
|
||||||
"cadetblue": [95, 158, 160],
|
|
||||||
"chartreuse": [127, 255, 0],
|
|
||||||
"chocolate": [210, 105, 30],
|
|
||||||
"coral": [255, 127, 80],
|
|
||||||
"cornflowerblue": [100, 149, 237],
|
|
||||||
"cornsilk": [255, 248, 220],
|
|
||||||
"crimson": [220, 20, 60],
|
|
||||||
"cyan": [0, 255, 255],
|
|
||||||
"darkblue": [0, 0, 139],
|
|
||||||
"darkcyan": [0, 139, 139],
|
|
||||||
"darkgoldenrod": [184, 134, 11],
|
|
||||||
"darkgray": [169, 169, 169],
|
|
||||||
"darkgreen": [0, 100, 0],
|
|
||||||
"darkgrey": [169, 169, 169],
|
|
||||||
"darkkhaki": [189, 183, 107],
|
|
||||||
"darkmagenta": [139, 0, 139],
|
|
||||||
"darkolivegreen": [85, 107, 47],
|
|
||||||
"darkorange": [255, 140, 0],
|
|
||||||
"darkorchid": [153, 50, 204],
|
|
||||||
"darkred": [139, 0, 0],
|
|
||||||
"darksalmon": [233, 150, 122],
|
|
||||||
"darkseagreen": [143, 188, 143],
|
|
||||||
"darkslateblue": [72, 61, 139],
|
|
||||||
"darkslategray": [47, 79, 79],
|
|
||||||
"darkslategrey": [47, 79, 79],
|
|
||||||
"darkturquoise": [0, 206, 209],
|
|
||||||
"darkviolet": [148, 0, 211],
|
|
||||||
"deeppink": [255, 20, 147],
|
|
||||||
"deepskyblue": [0, 191, 255],
|
|
||||||
"dimgray": [105, 105, 105],
|
|
||||||
"dimgrey": [105, 105, 105],
|
|
||||||
"dodgerblue": [30, 144, 255],
|
|
||||||
"firebrick": [178, 34, 34],
|
|
||||||
"floralwhite": [255, 250, 240],
|
|
||||||
"forestgreen": [34, 139, 34],
|
|
||||||
"fuchsia": [255, 0, 255],
|
|
||||||
"gainsboro": [220, 220, 220],
|
|
||||||
"ghostwhite": [248, 248, 255],
|
|
||||||
"gold": [255, 215, 0],
|
|
||||||
"goldenrod": [218, 165, 32],
|
|
||||||
"gray": [128, 128, 128],
|
|
||||||
"green": [0, 128, 0],
|
|
||||||
"greenyellow": [173, 255, 47],
|
|
||||||
"grey": [128, 128, 128],
|
|
||||||
"honeydew": [240, 255, 240],
|
|
||||||
"hotpink": [255, 105, 180],
|
|
||||||
"indianred": [205, 92, 92],
|
|
||||||
"indigo": [75, 0, 130],
|
|
||||||
"ivory": [255, 255, 240],
|
|
||||||
"khaki": [240, 230, 140],
|
|
||||||
"lavender": [230, 230, 250],
|
|
||||||
"lavenderblush": [255, 240, 245],
|
|
||||||
"lawngreen": [124, 252, 0],
|
|
||||||
"lemonchiffon": [255, 250, 205],
|
|
||||||
"lightblue": [173, 216, 230],
|
|
||||||
"lightcoral": [240, 128, 128],
|
|
||||||
"lightcyan": [224, 255, 255],
|
|
||||||
"lightgoldenrodyellow": [250, 250, 210],
|
|
||||||
"lightgray": [211, 211, 211],
|
|
||||||
"lightgreen": [144, 238, 144],
|
|
||||||
"lightgrey": [211, 211, 211],
|
|
||||||
"lightpink": [255, 182, 193],
|
|
||||||
"lightsalmon": [255, 160, 122],
|
|
||||||
"lightseagreen": [32, 178, 170],
|
|
||||||
"lightskyblue": [135, 206, 250],
|
|
||||||
"lightslategray": [119, 136, 153],
|
|
||||||
"lightslategrey": [119, 136, 153],
|
|
||||||
"lightsteelblue": [176, 196, 222],
|
|
||||||
"lightyellow": [255, 255, 224],
|
|
||||||
"lime": [0, 255, 0],
|
|
||||||
"limegreen": [50, 205, 50],
|
|
||||||
"linen": [250, 240, 230],
|
|
||||||
"magenta": [255, 0, 255],
|
|
||||||
"maroon": [128, 0, 0],
|
|
||||||
"mediumaquamarine": [102, 205, 170],
|
|
||||||
"mediumblue": [0, 0, 205],
|
|
||||||
"mediumorchid": [186, 85, 211],
|
|
||||||
"mediumpurple": [147, 112, 219],
|
|
||||||
"mediumseagreen": [60, 179, 113],
|
|
||||||
"mediumslateblue": [123, 104, 238],
|
|
||||||
"mediumspringgreen": [0, 250, 154],
|
|
||||||
"mediumturquoise": [72, 209, 204],
|
|
||||||
"mediumvioletred": [199, 21, 133],
|
|
||||||
"midnightblue": [25, 25, 112],
|
|
||||||
"mintcream": [245, 255, 250],
|
|
||||||
"mistyrose": [255, 228, 225],
|
|
||||||
"moccasin": [255, 228, 181],
|
|
||||||
"navajowhite": [255, 222, 173],
|
|
||||||
"navy": [0, 0, 128],
|
|
||||||
"oldlace": [253, 245, 230],
|
|
||||||
"olive": [128, 128, 0],
|
|
||||||
"olivedrab": [107, 142, 35],
|
|
||||||
"orange": [255, 165, 0],
|
|
||||||
"orangered": [255, 69, 0],
|
|
||||||
"orchid": [218, 112, 214],
|
|
||||||
"palegoldenrod": [238, 232, 170],
|
|
||||||
"palegreen": [152, 251, 152],
|
|
||||||
"paleturquoise": [175, 238, 238],
|
|
||||||
"palevioletred": [219, 112, 147],
|
|
||||||
"papayawhip": [255, 239, 213],
|
|
||||||
"peachpuff": [255, 218, 185],
|
|
||||||
"peru": [205, 133, 63],
|
|
||||||
"pink": [255, 192, 203],
|
|
||||||
"plum": [221, 160, 221],
|
|
||||||
"powderblue": [176, 224, 230],
|
|
||||||
"purple": [128, 0, 128],
|
|
||||||
"rebeccapurple": [102, 51, 153],
|
|
||||||
"red": [255, 0, 0],
|
|
||||||
"rosybrown": [188, 143, 143],
|
|
||||||
"royalblue": [65, 105, 225],
|
|
||||||
"saddlebrown": [139, 69, 19],
|
|
||||||
"salmon": [250, 128, 114],
|
|
||||||
"sandybrown": [244, 164, 96],
|
|
||||||
"seagreen": [46, 139, 87],
|
|
||||||
"seashell": [255, 245, 238],
|
|
||||||
"sienna": [160, 82, 45],
|
|
||||||
"silver": [192, 192, 192],
|
|
||||||
"skyblue": [135, 206, 235],
|
|
||||||
"slateblue": [106, 90, 205],
|
|
||||||
"slategray": [112, 128, 144],
|
|
||||||
"slategrey": [112, 128, 144],
|
|
||||||
"snow": [255, 250, 250],
|
|
||||||
"springgreen": [0, 255, 127],
|
|
||||||
"steelblue": [70, 130, 180],
|
|
||||||
"tan": [210, 180, 140],
|
|
||||||
"teal": [0, 128, 128],
|
|
||||||
"thistle": [216, 191, 216],
|
|
||||||
"tomato": [255, 99, 71],
|
|
||||||
"turquoise": [64, 224, 208],
|
|
||||||
"violet": [238, 130, 238],
|
|
||||||
"wheat": [245, 222, 179],
|
|
||||||
"white": [255, 255, 255],
|
|
||||||
"whitesmoke": [245, 245, 245],
|
|
||||||
"yellow": [255, 255, 0],
|
|
||||||
"yellowgreen": [154, 205, 50]
|
|
||||||
};
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"name": "color-name",
|
|
||||||
"version": "1.1.3",
|
|
||||||
"description": "A list of color names and its values",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "node test.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git@github.com:dfcreative/color-name.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"color-name",
|
|
||||||
"color",
|
|
||||||
"color-keyword",
|
|
||||||
"keyword"
|
|
||||||
],
|
|
||||||
"author": "DY <dfcreative@gmail.com>",
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/dfcreative/color-name/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/dfcreative/color-name"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
'use strict'
|
|
||||||
|
|
||||||
var names = require('./');
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
assert.deepEqual(names.red, [255,0,0]);
|
|
||||||
assert.deepEqual(names.aliceblue, [240,248,255]);
|
|
|
@ -1,11 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
|
|
||||||
|
|
||||||
module.exports = function (str) {
|
|
||||||
if (typeof str !== 'string') {
|
|
||||||
throw new TypeError('Expected a string');
|
|
||||||
}
|
|
||||||
|
|
||||||
return str.replace(matchOperatorsRe, '\\$&');
|
|
||||||
};
|
|
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
|
@ -1,41 +0,0 @@
|
||||||
{
|
|
||||||
"name": "escape-string-regexp",
|
|
||||||
"version": "1.0.5",
|
|
||||||
"description": "Escape RegExp special characters",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": "sindresorhus/escape-string-regexp",
|
|
||||||
"author": {
|
|
||||||
"name": "Sindre Sorhus",
|
|
||||||
"email": "sindresorhus@gmail.com",
|
|
||||||
"url": "sindresorhus.com"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
"Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)",
|
|
||||||
"Joshua Boy Nicolai Appelman <joshua@jbna.nl> (jbna.nl)"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "xo && ava"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"index.js"
|
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"escape",
|
|
||||||
"regex",
|
|
||||||
"regexp",
|
|
||||||
"re",
|
|
||||||
"regular",
|
|
||||||
"expression",
|
|
||||||
"string",
|
|
||||||
"str",
|
|
||||||
"special",
|
|
||||||
"characters"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
|
||||||
"ava": "*",
|
|
||||||
"xo": "*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
# escape-string-regexp [![Build Status](https://travis-ci.org/sindresorhus/escape-string-regexp.svg?branch=master)](https://travis-ci.org/sindresorhus/escape-string-regexp)
|
|
||||||
|
|
||||||
> Escape RegExp special characters
|
|
||||||
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
```
|
|
||||||
$ npm install --save escape-string-regexp
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
const escapeStringRegexp = require('escape-string-regexp');
|
|
||||||
|
|
||||||
const escapedString = escapeStringRegexp('how much $ for a unicorn?');
|
|
||||||
//=> 'how much \$ for a unicorn\?'
|
|
||||||
|
|
||||||
new RegExp(escapedString);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
|
|
@ -1,8 +0,0 @@
|
||||||
'use strict';
|
|
||||||
module.exports = (flag, argv) => {
|
|
||||||
argv = argv || process.argv;
|
|
||||||
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
|
|
||||||
const pos = argv.indexOf(prefix + flag);
|
|
||||||
const terminatorPos = argv.indexOf('--');
|
|
||||||
return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
|
|
||||||
};
|
|
|
@ -1,9 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"name": "has-flag",
|
|
||||||
"version": "3.0.0",
|
|
||||||
"description": "Check if argv has a specific flag",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": "sindresorhus/has-flag",
|
|
||||||
"author": {
|
|
||||||
"name": "Sindre Sorhus",
|
|
||||||
"email": "sindresorhus@gmail.com",
|
|
||||||
"url": "sindresorhus.com"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "xo && ava"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"index.js"
|
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"has",
|
|
||||||
"check",
|
|
||||||
"detect",
|
|
||||||
"contains",
|
|
||||||
"find",
|
|
||||||
"flag",
|
|
||||||
"cli",
|
|
||||||
"command-line",
|
|
||||||
"argv",
|
|
||||||
"process",
|
|
||||||
"arg",
|
|
||||||
"args",
|
|
||||||
"argument",
|
|
||||||
"arguments",
|
|
||||||
"getopt",
|
|
||||||
"minimist",
|
|
||||||
"optimist"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
|
||||||
"ava": "*",
|
|
||||||
"xo": "*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
# has-flag [![Build Status](https://travis-ci.org/sindresorhus/has-flag.svg?branch=master)](https://travis-ci.org/sindresorhus/has-flag)
|
|
||||||
|
|
||||||
> Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag
|
|
||||||
|
|
||||||
Correctly stops looking after an `--` argument terminator.
|
|
||||||
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
```
|
|
||||||
$ npm install has-flag
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
// foo.js
|
|
||||||
const hasFlag = require('has-flag');
|
|
||||||
|
|
||||||
hasFlag('unicorn');
|
|
||||||
//=> true
|
|
||||||
|
|
||||||
hasFlag('--unicorn');
|
|
||||||
//=> true
|
|
||||||
|
|
||||||
hasFlag('f');
|
|
||||||
//=> true
|
|
||||||
|
|
||||||
hasFlag('-f');
|
|
||||||
//=> true
|
|
||||||
|
|
||||||
hasFlag('foo=bar');
|
|
||||||
//=> true
|
|
||||||
|
|
||||||
hasFlag('foo');
|
|
||||||
//=> false
|
|
||||||
|
|
||||||
hasFlag('rainbow');
|
|
||||||
//=> false
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
$ node foo.js -f --unicorn --foo=bar -- --rainbow
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### hasFlag(flag, [argv])
|
|
||||||
|
|
||||||
Returns a boolean for whether the flag exists.
|
|
||||||
|
|
||||||
#### flag
|
|
||||||
|
|
||||||
Type: `string`
|
|
||||||
|
|
||||||
CLI flag to look for. The `--` prefix is optional.
|
|
||||||
|
|
||||||
#### argv
|
|
||||||
|
|
||||||
Type: `string[]`<br>
|
|
||||||
Default: `process.argv`
|
|
||||||
|
|
||||||
CLI arguments.
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
|
|
@ -1,5 +0,0 @@
|
||||||
'use strict';
|
|
||||||
module.exports = {
|
|
||||||
stdout: false,
|
|
||||||
stderr: false
|
|
||||||
};
|
|
|
@ -1,131 +0,0 @@
|
||||||
'use strict';
|
|
||||||
const os = require('os');
|
|
||||||
const hasFlag = require('has-flag');
|
|
||||||
|
|
||||||
const env = process.env;
|
|
||||||
|
|
||||||
let forceColor;
|
|
||||||
if (hasFlag('no-color') ||
|
|
||||||
hasFlag('no-colors') ||
|
|
||||||
hasFlag('color=false')) {
|
|
||||||
forceColor = false;
|
|
||||||
} else if (hasFlag('color') ||
|
|
||||||
hasFlag('colors') ||
|
|
||||||
hasFlag('color=true') ||
|
|
||||||
hasFlag('color=always')) {
|
|
||||||
forceColor = true;
|
|
||||||
}
|
|
||||||
if ('FORCE_COLOR' in env) {
|
|
||||||
forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function translateLevel(level) {
|
|
||||||
if (level === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
level,
|
|
||||||
hasBasic: true,
|
|
||||||
has256: level >= 2,
|
|
||||||
has16m: level >= 3
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function supportsColor(stream) {
|
|
||||||
if (forceColor === false) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasFlag('color=16m') ||
|
|
||||||
hasFlag('color=full') ||
|
|
||||||
hasFlag('color=truecolor')) {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasFlag('color=256')) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream && !stream.isTTY && forceColor !== true) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const min = forceColor ? 1 : 0;
|
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
// Node.js 7.5.0 is the first version of Node.js to include a patch to
|
|
||||||
// libuv that enables 256 color output on Windows. Anything earlier and it
|
|
||||||
// won't work. However, here we target Node.js 8 at minimum as it is an LTS
|
|
||||||
// release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
|
|
||||||
// release that supports 256 colors. Windows 10 build 14931 is the first release
|
|
||||||
// that supports 16m/TrueColor.
|
|
||||||
const osRelease = os.release().split('.');
|
|
||||||
if (
|
|
||||||
Number(process.versions.node.split('.')[0]) >= 8 &&
|
|
||||||
Number(osRelease[0]) >= 10 &&
|
|
||||||
Number(osRelease[2]) >= 10586
|
|
||||||
) {
|
|
||||||
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('CI' in env) {
|
|
||||||
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('TEAMCITY_VERSION' in env) {
|
|
||||||
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env.COLORTERM === 'truecolor') {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('TERM_PROGRAM' in env) {
|
|
||||||
const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
|
|
||||||
|
|
||||||
switch (env.TERM_PROGRAM) {
|
|
||||||
case 'iTerm.app':
|
|
||||||
return version >= 3 ? 3 : 2;
|
|
||||||
case 'Apple_Terminal':
|
|
||||||
return 2;
|
|
||||||
// No default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/-256(color)?$/i.test(env.TERM)) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('COLORTERM' in env) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env.TERM === 'dumb') {
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSupportLevel(stream) {
|
|
||||||
const level = supportsColor(stream);
|
|
||||||
return translateLevel(level);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
supportsColor: getSupportLevel,
|
|
||||||
stdout: getSupportLevel(process.stdout),
|
|
||||||
stderr: getSupportLevel(process.stderr)
|
|
||||||
};
|
|
|
@ -1,9 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,53 +0,0 @@
|
||||||
{
|
|
||||||
"name": "supports-color",
|
|
||||||
"version": "5.5.0",
|
|
||||||
"description": "Detect whether a terminal supports color",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": "chalk/supports-color",
|
|
||||||
"author": {
|
|
||||||
"name": "Sindre Sorhus",
|
|
||||||
"email": "sindresorhus@gmail.com",
|
|
||||||
"url": "sindresorhus.com"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "xo && ava"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"index.js",
|
|
||||||
"browser.js"
|
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"color",
|
|
||||||
"colour",
|
|
||||||
"colors",
|
|
||||||
"terminal",
|
|
||||||
"console",
|
|
||||||
"cli",
|
|
||||||
"ansi",
|
|
||||||
"styles",
|
|
||||||
"tty",
|
|
||||||
"rgb",
|
|
||||||
"256",
|
|
||||||
"shell",
|
|
||||||
"xterm",
|
|
||||||
"command-line",
|
|
||||||
"support",
|
|
||||||
"supports",
|
|
||||||
"capability",
|
|
||||||
"detect",
|
|
||||||
"truecolor",
|
|
||||||
"16m"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"ava": "^0.25.0",
|
|
||||||
"import-fresh": "^2.0.0",
|
|
||||||
"xo": "^0.20.0"
|
|
||||||
},
|
|
||||||
"browser": "browser.js"
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color)
|
|
||||||
|
|
||||||
> Detect whether a terminal supports color
|
|
||||||
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
```
|
|
||||||
$ npm install supports-color
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
const supportsColor = require('supports-color');
|
|
||||||
|
|
||||||
if (supportsColor.stdout) {
|
|
||||||
console.log('Terminal stdout supports color');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportsColor.stdout.has256) {
|
|
||||||
console.log('Terminal stdout supports 256 colors');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportsColor.stderr.has16m) {
|
|
||||||
console.log('Terminal stderr supports 16 million colors (truecolor)');
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported.
|
|
||||||
|
|
||||||
The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag:
|
|
||||||
|
|
||||||
- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors)
|
|
||||||
- `.level = 2` and `.has256 = true`: 256 color support
|
|
||||||
- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors)
|
|
||||||
|
|
||||||
|
|
||||||
## Info
|
|
||||||
|
|
||||||
It obeys the `--color` and `--no-color` CLI flags.
|
|
||||||
|
|
||||||
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
|
|
||||||
|
|
||||||
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
|
|
||||||
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module
|
|
||||||
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
|
|
||||||
|
|
||||||
|
|
||||||
## Maintainers
|
|
||||||
|
|
||||||
- [Sindre Sorhus](https://github.com/sindresorhus)
|
|
||||||
- [Josh Junon](https://github.com/qix-)
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@babel/highlight",
|
|
||||||
"version": "7.14.5",
|
|
||||||
"description": "Syntax highlight JavaScript strings for output in terminals.",
|
|
||||||
"author": "The Babel Team (https://babel.dev/team)",
|
|
||||||
"homepage": "https://babel.dev/docs/en/next/babel-highlight",
|
|
||||||
"license": "MIT",
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/babel/babel.git",
|
|
||||||
"directory": "packages/babel-highlight"
|
|
||||||
},
|
|
||||||
"main": "./lib/index.js",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/helper-validator-identifier": "^7.14.5",
|
|
||||||
"chalk": "^2.0.0",
|
|
||||||
"js-tokens": "^4.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/chalk": "^2.0.0",
|
|
||||||
"strip-ansi": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
v0.4.3 - July 17, 2021
|
|
||||||
|
|
||||||
* [`ce78027`](https://github.com/eslint/eslintrc/commit/ce78027f6a319a29fdf0b78ac1e7071373acffc4) Fix: ensure config files are files (#42) (Tom Jenkinson)
|
|
||||||
* [`95b1c9b`](https://github.com/eslint/eslintrc/commit/95b1c9b30267479a75cd07768f8f9e9cfa63c105) Chore: pin fs-teardown@0.1.1 (#45) (Milos Djermanovic)
|
|
||||||
* [`593fbe3`](https://github.com/eslint/eslintrc/commit/593fbe3c2c1c5f723f71810963ed21a56caed4c1) Chore: fix failing test (#44) (Tom Jenkinson)
|
|
||||||
|
|
||||||
v0.4.2 - June 4, 2021
|
|
||||||
|
|
||||||
* [`cc79a4d`](https://github.com/eslint/eslintrc/commit/cc79a4db45a2ca0236a846ed8eba28eea07d4db5) Upgrade: update globals to version 13.6 (#32) (Rouven Weßling)
|
|
||||||
|
|
||||||
v0.4.1 - May 7, 2021
|
|
||||||
|
|
||||||
* [`aa38ef4`](https://github.com/eslint/eslintrc/commit/aa38ef40c3123f8f534c7f9b0b7c306f5f011dce) Fix: Properly export module resolver (#34) (Richie Bendall)
|
|
||||||
* [`62ea4bd`](https://github.com/eslint/eslintrc/commit/62ea4bd74b78fbeff12ffb21f1f978817601d4d1) Build: add node v16 (#33) (薛定谔的猫)
|
|
||||||
* [`7c43d77`](https://github.com/eslint/eslintrc/commit/7c43d7784e39cf0b7b102af64f703cade11252bb) Chore: add tests for built-in rules config schema validation (fixes #15) (#31) (Milos Djermanovic)
|
|
||||||
* [`d8ea601`](https://github.com/eslint/eslintrc/commit/d8ea601ecb4b9f81cdc332b012b6b1bbc984366c) Chore: Test on Node 15.x (#30) (Milos Djermanovic)
|
|
||||||
* [`0b2f80d`](https://github.com/eslint/eslintrc/commit/0b2f80d6f6b33e4c5e168b08468867653f726754) Chore: lint test files (#18) (Milos Djermanovic)
|
|
||||||
|
|
||||||
v0.4.0 - February 27, 2021
|
|
||||||
|
|
||||||
* [`d9a527b`](https://github.com/eslint/eslintrc/commit/d9a527bdb16af46a28d37fa9022131149970a438) New: Implement DotCompat class (#20) (Nicholas C. Zakas)
|
|
||||||
* [`dac76c0`](https://github.com/eslint/eslintrc/commit/dac76c035a9ab9d315050f688867373966aab288) Chore: Replace usage of lodash with cache set (#29) (Tim van der Lippe)
|
|
||||||
* [`3ae2d77`](https://github.com/eslint/eslintrc/commit/3ae2d770cb810c026de817e6861e25dac111da9f) Update: add AggregateError global to es2021 environment (#28) (Milos Djermanovic)
|
|
||||||
|
|
||||||
v0.3.0 - January 15, 2021
|
|
||||||
|
|
||||||
* [`5184490`](https://github.com/eslint/eslintrc/commit/51844902bc4132f264f05a0614f2cdeb89290f68) Upgrade: lodash@4.17.20 (#24) (Milos Djermanovic)
|
|
||||||
* [`f1179c5`](https://github.com/eslint/eslintrc/commit/f1179c587ae09fabb5c3402598363cfcec2494f7) Update: Implement missing functionality from ESLint port (fixes #12) (#23) (Nicholas C. Zakas)
|
|
||||||
|
|
||||||
v0.2.2 - December 5, 2020
|
|
||||||
|
|
||||||
* [`1746840`](https://github.com/eslint/eslintrc/commit/17468407c1baf05747cb261c91f7f7b7c2a82422) Fix: include loadRules in internalSlotsMap cache (#19) (Henry Q. Dineen)
|
|
||||||
* [`f30bb49`](https://github.com/eslint/eslintrc/commit/f30bb4935aaf3f4c1b268490da495a59647e58d8) Chore: Test fixes for CascadingConfigArrayFactory (#17) (Nicholas C. Zakas)
|
|
||||||
* [`4440df8`](https://github.com/eslint/eslintrc/commit/4440df8237a127e15cbde5c697353e1224f12ec1) Chore: Fix config-array tests (#16) (Nicholas C. Zakas)
|
|
||||||
* [`7890e02`](https://github.com/eslint/eslintrc/commit/7890e027df530a0fb53bcf5751c8c7a008b2a494) Chore: Test fixes for config-array-factory.js (#13) (Nicholas C. Zakas)
|
|
||||||
|
|
||||||
v0.2.1 - October 26, 2020
|
|
||||||
|
|
||||||
* [`8b202ff`](https://github.com/eslint/eslintrc/commit/8b202ff866a39efdaad6394fde9f88372afbfca8) Fix: validate schema for built-in rules (#14) (Milos Djermanovic)
|
|
||||||
* [`04f3cae`](https://github.com/eslint/eslintrc/commit/04f3cae17fe07b2fd0b74fd3e88482b3094e75e3) Fix: cache compiled config schema (#9) (Milos Djermanovic)
|
|
||||||
|
|
||||||
v0.2.0 - October 16, 2020
|
|
||||||
|
|
||||||
* [`cb12255`](https://github.com/eslint/eslintrc/commit/cb12255b85390e932e1942e479c2c97310149390) Update: Allow eslint:all and eslint:recommended paths to be passed in (#11) (Nicholas C. Zakas)
|
|
||||||
* [`a75bacd`](https://github.com/eslint/eslintrc/commit/a75bacd9a743a7bbcdb8c59e5d4f9de3dc8b0f20) Chore: use GitHub Actions (#10) (Milos Djermanovic)
|
|
||||||
|
|
||||||
v0.1.3 - September 1, 2020
|
|
||||||
|
|
||||||
* [`8647a61`](https://github.com/eslint/eslintrc/commit/8647a61991fe121f923d33e96232475209b78210) Fix: version number and eslint-release version (refs #6) (Nicholas C. Zakas)
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 ESLint
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,61 +0,0 @@
|
||||||
# ESLintRC Library
|
|
||||||
|
|
||||||
This repository contains the legacy ESLintRC configuration file format for ESLint.
|
|
||||||
|
|
||||||
**Note:** This package is not intended for use outside of the ESLint ecosystem. It is ESLint-specific and not intended for use in other programs.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
You can install the package as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install @eslint/eslintrc --save-dev
|
|
||||||
|
|
||||||
# or
|
|
||||||
|
|
||||||
yarn add @eslint/eslintrc -D
|
|
||||||
```
|
|
||||||
|
|
||||||
## Future Usage
|
|
||||||
|
|
||||||
**Note:** This package is not intended for public use at this time. The following is an example of how it will be used in the future.
|
|
||||||
|
|
||||||
The primary class in this package is `FlatCompat`, which is a utility to translate ESLintRC-style configs into flat configs. Here's how you use it inside of your `eslint.config.js` file:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { FlatCompat } from "@eslint/eslintrc";
|
|
||||||
|
|
||||||
const compat = new FlatCompat();
|
|
||||||
|
|
||||||
export default [
|
|
||||||
|
|
||||||
// mimic ESLintRC-style extends
|
|
||||||
compat.extends("standard", "example"),
|
|
||||||
|
|
||||||
// mimic environments
|
|
||||||
compat.env({
|
|
||||||
es2020: true,
|
|
||||||
node: true
|
|
||||||
}),
|
|
||||||
|
|
||||||
// mimic plugins
|
|
||||||
compat.plugins("airbnb", "react"),
|
|
||||||
|
|
||||||
// translate an entire config
|
|
||||||
compat.config({
|
|
||||||
plugins: ["airbnb", "react"],
|
|
||||||
extends: "standard",
|
|
||||||
env: {
|
|
||||||
es2020: true,
|
|
||||||
node: true
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
semi: "error"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT License
|
|
|
@ -1,81 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Defines a schema for configs.
|
|
||||||
* @author Sylvan Mably
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const baseConfigProperties = {
|
|
||||||
$schema: { type: "string" },
|
|
||||||
env: { type: "object" },
|
|
||||||
extends: { $ref: "#/definitions/stringOrStrings" },
|
|
||||||
globals: { type: "object" },
|
|
||||||
overrides: {
|
|
||||||
type: "array",
|
|
||||||
items: { $ref: "#/definitions/overrideConfig" },
|
|
||||||
additionalItems: false
|
|
||||||
},
|
|
||||||
parser: { type: ["string", "null"] },
|
|
||||||
parserOptions: { type: "object" },
|
|
||||||
plugins: { type: "array" },
|
|
||||||
processor: { type: "string" },
|
|
||||||
rules: { type: "object" },
|
|
||||||
settings: { type: "object" },
|
|
||||||
noInlineConfig: { type: "boolean" },
|
|
||||||
reportUnusedDisableDirectives: { type: "boolean" },
|
|
||||||
|
|
||||||
ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
|
|
||||||
};
|
|
||||||
|
|
||||||
const configSchema = {
|
|
||||||
definitions: {
|
|
||||||
stringOrStrings: {
|
|
||||||
oneOf: [
|
|
||||||
{ type: "string" },
|
|
||||||
{
|
|
||||||
type: "array",
|
|
||||||
items: { type: "string" },
|
|
||||||
additionalItems: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
stringOrStringsRequired: {
|
|
||||||
oneOf: [
|
|
||||||
{ type: "string" },
|
|
||||||
{
|
|
||||||
type: "array",
|
|
||||||
items: { type: "string" },
|
|
||||||
additionalItems: false,
|
|
||||||
minItems: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Config at top-level.
|
|
||||||
objectConfig: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
root: { type: "boolean" },
|
|
||||||
ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
|
|
||||||
...baseConfigProperties
|
|
||||||
},
|
|
||||||
additionalProperties: false
|
|
||||||
},
|
|
||||||
|
|
||||||
// Config in `overrides`.
|
|
||||||
overrideConfig: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
excludedFiles: { $ref: "#/definitions/stringOrStrings" },
|
|
||||||
files: { $ref: "#/definitions/stringOrStringsRequired" },
|
|
||||||
...baseConfigProperties
|
|
||||||
},
|
|
||||||
required: ["files"],
|
|
||||||
additionalProperties: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
$ref: "#/definitions/objectConfig"
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = configSchema;
|
|
|
@ -1,180 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Defines environment settings and globals.
|
|
||||||
* @author Elan Shanker
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const globals = require("globals");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the object that has difference.
|
|
||||||
* @param {Record<string,boolean>} current The newer object.
|
|
||||||
* @param {Record<string,boolean>} prev The older object.
|
|
||||||
* @returns {Record<string,boolean>} The difference object.
|
|
||||||
*/
|
|
||||||
function getDiff(current, prev) {
|
|
||||||
const retv = {};
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(current)) {
|
|
||||||
if (!Object.hasOwnProperty.call(prev, key)) {
|
|
||||||
retv[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retv;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newGlobals2015 = getDiff(globals.es2015, globals.es5); // 19 variables such as Promise, Map, ...
|
|
||||||
const newGlobals2017 = {
|
|
||||||
Atomics: false,
|
|
||||||
SharedArrayBuffer: false
|
|
||||||
};
|
|
||||||
const newGlobals2020 = {
|
|
||||||
BigInt: false,
|
|
||||||
BigInt64Array: false,
|
|
||||||
BigUint64Array: false,
|
|
||||||
globalThis: false
|
|
||||||
};
|
|
||||||
|
|
||||||
const newGlobals2021 = {
|
|
||||||
AggregateError: false,
|
|
||||||
FinalizationRegistry: false,
|
|
||||||
WeakRef: false
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** @type {Map<string, import("../lib/shared/types").Environment>} */
|
|
||||||
module.exports = new Map(Object.entries({
|
|
||||||
|
|
||||||
// Language
|
|
||||||
builtin: {
|
|
||||||
globals: globals.es5
|
|
||||||
},
|
|
||||||
es6: {
|
|
||||||
globals: newGlobals2015,
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
es2015: {
|
|
||||||
globals: newGlobals2015,
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
es2017: {
|
|
||||||
globals: { ...newGlobals2015, ...newGlobals2017 },
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 8
|
|
||||||
}
|
|
||||||
},
|
|
||||||
es2020: {
|
|
||||||
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 11
|
|
||||||
}
|
|
||||||
},
|
|
||||||
es2021: {
|
|
||||||
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 12
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Platforms
|
|
||||||
browser: {
|
|
||||||
globals: globals.browser
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
globals: globals.node,
|
|
||||||
parserOptions: {
|
|
||||||
ecmaFeatures: {
|
|
||||||
globalReturn: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shared-node-browser": {
|
|
||||||
globals: globals["shared-node-browser"]
|
|
||||||
},
|
|
||||||
worker: {
|
|
||||||
globals: globals.worker
|
|
||||||
},
|
|
||||||
serviceworker: {
|
|
||||||
globals: globals.serviceworker
|
|
||||||
},
|
|
||||||
|
|
||||||
// Frameworks
|
|
||||||
commonjs: {
|
|
||||||
globals: globals.commonjs,
|
|
||||||
parserOptions: {
|
|
||||||
ecmaFeatures: {
|
|
||||||
globalReturn: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
amd: {
|
|
||||||
globals: globals.amd
|
|
||||||
},
|
|
||||||
mocha: {
|
|
||||||
globals: globals.mocha
|
|
||||||
},
|
|
||||||
jasmine: {
|
|
||||||
globals: globals.jasmine
|
|
||||||
},
|
|
||||||
jest: {
|
|
||||||
globals: globals.jest
|
|
||||||
},
|
|
||||||
phantomjs: {
|
|
||||||
globals: globals.phantomjs
|
|
||||||
},
|
|
||||||
jquery: {
|
|
||||||
globals: globals.jquery
|
|
||||||
},
|
|
||||||
qunit: {
|
|
||||||
globals: globals.qunit
|
|
||||||
},
|
|
||||||
prototypejs: {
|
|
||||||
globals: globals.prototypejs
|
|
||||||
},
|
|
||||||
shelljs: {
|
|
||||||
globals: globals.shelljs
|
|
||||||
},
|
|
||||||
meteor: {
|
|
||||||
globals: globals.meteor
|
|
||||||
},
|
|
||||||
mongo: {
|
|
||||||
globals: globals.mongo
|
|
||||||
},
|
|
||||||
protractor: {
|
|
||||||
globals: globals.protractor
|
|
||||||
},
|
|
||||||
applescript: {
|
|
||||||
globals: globals.applescript
|
|
||||||
},
|
|
||||||
nashorn: {
|
|
||||||
globals: globals.nashorn
|
|
||||||
},
|
|
||||||
atomtest: {
|
|
||||||
globals: globals.atomtest
|
|
||||||
},
|
|
||||||
embertest: {
|
|
||||||
globals: globals.embertest
|
|
||||||
},
|
|
||||||
webextensions: {
|
|
||||||
globals: globals.webextensions
|
|
||||||
},
|
|
||||||
greasemonkey: {
|
|
||||||
globals: globals.greasemonkey
|
|
||||||
}
|
|
||||||
}));
|
|
|
@ -1,12 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Stub eslint:all config
|
|
||||||
* @author Nicholas C. Zakas
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
settings: {
|
|
||||||
"eslint:all": true
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,12 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Stub eslint:recommended config
|
|
||||||
* @author Nicholas C. Zakas
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
settings: {
|
|
||||||
"eslint:recommended": true
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,519 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview `CascadingConfigArrayFactory` class.
|
|
||||||
*
|
|
||||||
* `CascadingConfigArrayFactory` class has a responsibility:
|
|
||||||
*
|
|
||||||
* 1. Handles cascading of config files.
|
|
||||||
*
|
|
||||||
* It provides two methods:
|
|
||||||
*
|
|
||||||
* - `getConfigArrayForFile(filePath)`
|
|
||||||
* Get the corresponded configuration of a given file. This method doesn't
|
|
||||||
* throw even if the given file didn't exist.
|
|
||||||
* - `clearCache()`
|
|
||||||
* Clear the internal cache. You have to call this method when
|
|
||||||
* `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
|
|
||||||
* on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
|
|
||||||
*
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const os = require("os");
|
|
||||||
const path = require("path");
|
|
||||||
const ConfigValidator = require("./shared/config-validator");
|
|
||||||
const { emitDeprecationWarning } = require("./shared/deprecation-warnings");
|
|
||||||
const { ConfigArrayFactory } = require("./config-array-factory");
|
|
||||||
const { ConfigArray, ConfigDependency, IgnorePattern } = require("./config-array");
|
|
||||||
const debug = require("debug")("eslintrc:cascading-config-array-factory");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Define types for VSCode IntelliSense.
|
|
||||||
/** @typedef {import("./shared/types").ConfigData} ConfigData */
|
|
||||||
/** @typedef {import("./shared/types").Parser} Parser */
|
|
||||||
/** @typedef {import("./shared/types").Plugin} Plugin */
|
|
||||||
/** @typedef {import("./shared/types").Rule} Rule */
|
|
||||||
/** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} CascadingConfigArrayFactoryOptions
|
|
||||||
* @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
|
|
||||||
* @property {ConfigData} [baseConfig] The config by `baseConfig` option.
|
|
||||||
* @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.
|
|
||||||
* @property {string} [cwd] The base directory to start lookup.
|
|
||||||
* @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
|
|
||||||
* @property {string[]} [rulePaths] The value of `--rulesdir` option.
|
|
||||||
* @property {string} [specificConfigPath] The value of `--config` option.
|
|
||||||
* @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
|
|
||||||
* @property {Function} loadRules The function to use to load rules.
|
|
||||||
* @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
|
|
||||||
* @property {Object} [resolver=ModuleResolver] The module resolver object.
|
|
||||||
* @property {string} eslintAllPath The path to the definitions for eslint:all.
|
|
||||||
* @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} CascadingConfigArrayFactoryInternalSlots
|
|
||||||
* @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
|
|
||||||
* @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
|
|
||||||
* @property {ConfigArray} cliConfigArray The config array of CLI options.
|
|
||||||
* @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
|
|
||||||
* @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
|
|
||||||
* @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
|
|
||||||
* @property {string} cwd The base directory to start lookup.
|
|
||||||
* @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
|
|
||||||
* @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
|
|
||||||
* @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
|
|
||||||
* @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
|
|
||||||
* @property {boolean} useEslintrc if `false` then it doesn't load config files.
|
|
||||||
* @property {Function} loadRules The function to use to load rules.
|
|
||||||
* @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
|
|
||||||
* @property {Object} [resolver=ModuleResolver] The module resolver object.
|
|
||||||
* @property {string} eslintAllPath The path to the definitions for eslint:all.
|
|
||||||
* @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
|
|
||||||
const internalSlotsMap = new WeakMap();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the config array from `baseConfig` and `rulePaths`.
|
|
||||||
* @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
|
|
||||||
* @returns {ConfigArray} The config array of the base configs.
|
|
||||||
*/
|
|
||||||
function createBaseConfigArray({
|
|
||||||
configArrayFactory,
|
|
||||||
baseConfigData,
|
|
||||||
rulePaths,
|
|
||||||
cwd,
|
|
||||||
loadRules
|
|
||||||
}) {
|
|
||||||
const baseConfigArray = configArrayFactory.create(
|
|
||||||
baseConfigData,
|
|
||||||
{ name: "BaseConfig" }
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create the config array element for the default ignore patterns.
|
|
||||||
* This element has `ignorePattern` property that ignores the default
|
|
||||||
* patterns in the current working directory.
|
|
||||||
*/
|
|
||||||
baseConfigArray.unshift(configArrayFactory.create(
|
|
||||||
{ ignorePatterns: IgnorePattern.DefaultPatterns },
|
|
||||||
{ name: "DefaultIgnorePattern" }
|
|
||||||
)[0]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load rules `--rulesdir` option as a pseudo plugin.
|
|
||||||
* Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
|
|
||||||
* the rule's options with only information in the config array.
|
|
||||||
*/
|
|
||||||
if (rulePaths && rulePaths.length > 0) {
|
|
||||||
baseConfigArray.push({
|
|
||||||
type: "config",
|
|
||||||
name: "--rulesdir",
|
|
||||||
filePath: "",
|
|
||||||
plugins: {
|
|
||||||
"": new ConfigDependency({
|
|
||||||
definition: {
|
|
||||||
rules: rulePaths.reduce(
|
|
||||||
(map, rulesPath) => Object.assign(
|
|
||||||
map,
|
|
||||||
loadRules(rulesPath, cwd)
|
|
||||||
),
|
|
||||||
{}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
filePath: "",
|
|
||||||
id: "",
|
|
||||||
importerName: "--rulesdir",
|
|
||||||
importerPath: ""
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return baseConfigArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the config array from CLI options.
|
|
||||||
* @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
|
|
||||||
* @returns {ConfigArray} The config array of the base configs.
|
|
||||||
*/
|
|
||||||
function createCLIConfigArray({
|
|
||||||
cliConfigData,
|
|
||||||
configArrayFactory,
|
|
||||||
cwd,
|
|
||||||
ignorePath,
|
|
||||||
specificConfigPath
|
|
||||||
}) {
|
|
||||||
const cliConfigArray = configArrayFactory.create(
|
|
||||||
cliConfigData,
|
|
||||||
{ name: "CLIOptions" }
|
|
||||||
);
|
|
||||||
|
|
||||||
cliConfigArray.unshift(
|
|
||||||
...(ignorePath
|
|
||||||
? configArrayFactory.loadESLintIgnore(ignorePath)
|
|
||||||
: configArrayFactory.loadDefaultESLintIgnore())
|
|
||||||
);
|
|
||||||
|
|
||||||
if (specificConfigPath) {
|
|
||||||
cliConfigArray.unshift(
|
|
||||||
...configArrayFactory.loadFile(
|
|
||||||
specificConfigPath,
|
|
||||||
{ name: "--config", basePath: cwd }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cliConfigArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The error type when there are files matched by a glob, but all of them have been ignored.
|
|
||||||
*/
|
|
||||||
class ConfigurationNotFoundError extends Error {
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/require-description
|
|
||||||
/**
|
|
||||||
* @param {string} directoryPath The directory path.
|
|
||||||
*/
|
|
||||||
constructor(directoryPath) {
|
|
||||||
super(`No ESLint configuration found in ${directoryPath}.`);
|
|
||||||
this.messageTemplate = "no-config-found";
|
|
||||||
this.messageData = { directoryPath };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class provides the functionality that enumerates every file which is
|
|
||||||
* matched by given glob patterns and that configuration.
|
|
||||||
*/
|
|
||||||
class CascadingConfigArrayFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this enumerator.
|
|
||||||
* @param {CascadingConfigArrayFactoryOptions} options The options.
|
|
||||||
*/
|
|
||||||
constructor({
|
|
||||||
additionalPluginPool = new Map(),
|
|
||||||
baseConfig: baseConfigData = null,
|
|
||||||
cliConfig: cliConfigData = null,
|
|
||||||
cwd = process.cwd(),
|
|
||||||
ignorePath,
|
|
||||||
resolvePluginsRelativeTo,
|
|
||||||
rulePaths = [],
|
|
||||||
specificConfigPath = null,
|
|
||||||
useEslintrc = true,
|
|
||||||
builtInRules = new Map(),
|
|
||||||
loadRules,
|
|
||||||
resolver,
|
|
||||||
eslintRecommendedPath,
|
|
||||||
eslintAllPath
|
|
||||||
} = {}) {
|
|
||||||
const configArrayFactory = new ConfigArrayFactory({
|
|
||||||
additionalPluginPool,
|
|
||||||
cwd,
|
|
||||||
resolvePluginsRelativeTo,
|
|
||||||
builtInRules,
|
|
||||||
resolver,
|
|
||||||
eslintRecommendedPath,
|
|
||||||
eslintAllPath
|
|
||||||
});
|
|
||||||
|
|
||||||
internalSlotsMap.set(this, {
|
|
||||||
baseConfigArray: createBaseConfigArray({
|
|
||||||
baseConfigData,
|
|
||||||
configArrayFactory,
|
|
||||||
cwd,
|
|
||||||
rulePaths,
|
|
||||||
loadRules,
|
|
||||||
resolver
|
|
||||||
}),
|
|
||||||
baseConfigData,
|
|
||||||
cliConfigArray: createCLIConfigArray({
|
|
||||||
cliConfigData,
|
|
||||||
configArrayFactory,
|
|
||||||
cwd,
|
|
||||||
ignorePath,
|
|
||||||
specificConfigPath
|
|
||||||
}),
|
|
||||||
cliConfigData,
|
|
||||||
configArrayFactory,
|
|
||||||
configCache: new Map(),
|
|
||||||
cwd,
|
|
||||||
finalizeCache: new WeakMap(),
|
|
||||||
ignorePath,
|
|
||||||
rulePaths,
|
|
||||||
specificConfigPath,
|
|
||||||
useEslintrc,
|
|
||||||
builtInRules,
|
|
||||||
loadRules
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path to the current working directory.
|
|
||||||
* This is used by tests.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
get cwd() {
|
|
||||||
const { cwd } = internalSlotsMap.get(this);
|
|
||||||
|
|
||||||
return cwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the config array of a given file.
|
|
||||||
* If `filePath` was not given, it returns the config which contains only
|
|
||||||
* `baseConfigData` and `cliConfigData`.
|
|
||||||
* @param {string} [filePath] The file path to a file.
|
|
||||||
* @param {Object} [options] The options.
|
|
||||||
* @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
|
|
||||||
* @returns {ConfigArray} The config array of the file.
|
|
||||||
*/
|
|
||||||
getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
|
|
||||||
const {
|
|
||||||
baseConfigArray,
|
|
||||||
cliConfigArray,
|
|
||||||
cwd
|
|
||||||
} = internalSlotsMap.get(this);
|
|
||||||
|
|
||||||
if (!filePath) {
|
|
||||||
return new ConfigArray(...baseConfigArray, ...cliConfigArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
const directoryPath = path.dirname(path.resolve(cwd, filePath));
|
|
||||||
|
|
||||||
debug(`Load config files for ${directoryPath}.`);
|
|
||||||
|
|
||||||
return this._finalizeConfigArray(
|
|
||||||
this._loadConfigInAncestors(directoryPath),
|
|
||||||
directoryPath,
|
|
||||||
ignoreNotFoundError
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the config data to override all configs.
|
|
||||||
* Require to call `clearCache()` method after this method is called.
|
|
||||||
* @param {ConfigData} configData The config data to override all configs.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
setOverrideConfig(configData) {
|
|
||||||
const slots = internalSlotsMap.get(this);
|
|
||||||
|
|
||||||
slots.cliConfigData = configData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear config cache.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
clearCache() {
|
|
||||||
const slots = internalSlotsMap.get(this);
|
|
||||||
|
|
||||||
slots.baseConfigArray = createBaseConfigArray(slots);
|
|
||||||
slots.cliConfigArray = createCLIConfigArray(slots);
|
|
||||||
slots.configCache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load and normalize config files from the ancestor directories.
|
|
||||||
* @param {string} directoryPath The path to a leaf directory.
|
|
||||||
* @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
|
|
||||||
* @returns {ConfigArray} The loaded config.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
|
|
||||||
const {
|
|
||||||
baseConfigArray,
|
|
||||||
configArrayFactory,
|
|
||||||
configCache,
|
|
||||||
cwd,
|
|
||||||
useEslintrc
|
|
||||||
} = internalSlotsMap.get(this);
|
|
||||||
|
|
||||||
if (!useEslintrc) {
|
|
||||||
return baseConfigArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
let configArray = configCache.get(directoryPath);
|
|
||||||
|
|
||||||
// Hit cache.
|
|
||||||
if (configArray) {
|
|
||||||
debug(`Cache hit: ${directoryPath}.`);
|
|
||||||
return configArray;
|
|
||||||
}
|
|
||||||
debug(`No cache found: ${directoryPath}.`);
|
|
||||||
|
|
||||||
const homePath = os.homedir();
|
|
||||||
|
|
||||||
// Consider this is root.
|
|
||||||
if (directoryPath === homePath && cwd !== homePath) {
|
|
||||||
debug("Stop traversing because of considered root.");
|
|
||||||
if (configsExistInSubdirs) {
|
|
||||||
const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
|
|
||||||
|
|
||||||
if (filePath) {
|
|
||||||
emitDeprecationWarning(
|
|
||||||
filePath,
|
|
||||||
"ESLINT_PERSONAL_CONFIG_SUPPRESS"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._cacheConfig(directoryPath, baseConfigArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the config on this directory.
|
|
||||||
try {
|
|
||||||
configArray = configArrayFactory.loadInDirectory(directoryPath);
|
|
||||||
} catch (error) {
|
|
||||||
/* istanbul ignore next */
|
|
||||||
if (error.code === "EACCES") {
|
|
||||||
debug("Stop traversing because of 'EACCES' error.");
|
|
||||||
return this._cacheConfig(directoryPath, baseConfigArray);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configArray.length > 0 && configArray.isRoot()) {
|
|
||||||
debug("Stop traversing because of 'root:true'.");
|
|
||||||
configArray.unshift(...baseConfigArray);
|
|
||||||
return this._cacheConfig(directoryPath, configArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load from the ancestors and merge it.
|
|
||||||
const parentPath = path.dirname(directoryPath);
|
|
||||||
const parentConfigArray = parentPath && parentPath !== directoryPath
|
|
||||||
? this._loadConfigInAncestors(
|
|
||||||
parentPath,
|
|
||||||
configsExistInSubdirs || configArray.length > 0
|
|
||||||
)
|
|
||||||
: baseConfigArray;
|
|
||||||
|
|
||||||
if (configArray.length > 0) {
|
|
||||||
configArray.unshift(...parentConfigArray);
|
|
||||||
} else {
|
|
||||||
configArray = parentConfigArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache and return.
|
|
||||||
return this._cacheConfig(directoryPath, configArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Freeze and cache a given config.
|
|
||||||
* @param {string} directoryPath The path to a directory as a cache key.
|
|
||||||
* @param {ConfigArray} configArray The config array as a cache value.
|
|
||||||
* @returns {ConfigArray} The `configArray` (frozen).
|
|
||||||
*/
|
|
||||||
_cacheConfig(directoryPath, configArray) {
|
|
||||||
const { configCache } = internalSlotsMap.get(this);
|
|
||||||
|
|
||||||
Object.freeze(configArray);
|
|
||||||
configCache.set(directoryPath, configArray);
|
|
||||||
|
|
||||||
return configArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalize a given config array.
|
|
||||||
* Concatenate `--config` and other CLI options.
|
|
||||||
* @param {ConfigArray} configArray The parent config array.
|
|
||||||
* @param {string} directoryPath The path to the leaf directory to find config files.
|
|
||||||
* @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
|
|
||||||
* @returns {ConfigArray} The loaded config.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
|
|
||||||
const {
|
|
||||||
cliConfigArray,
|
|
||||||
configArrayFactory,
|
|
||||||
finalizeCache,
|
|
||||||
useEslintrc,
|
|
||||||
builtInRules
|
|
||||||
} = internalSlotsMap.get(this);
|
|
||||||
|
|
||||||
let finalConfigArray = finalizeCache.get(configArray);
|
|
||||||
|
|
||||||
if (!finalConfigArray) {
|
|
||||||
finalConfigArray = configArray;
|
|
||||||
|
|
||||||
// Load the personal config if there are no regular config files.
|
|
||||||
if (
|
|
||||||
useEslintrc &&
|
|
||||||
configArray.every(c => !c.filePath) &&
|
|
||||||
cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
|
|
||||||
) {
|
|
||||||
const homePath = os.homedir();
|
|
||||||
|
|
||||||
debug("Loading the config file of the home directory:", homePath);
|
|
||||||
|
|
||||||
const personalConfigArray = configArrayFactory.loadInDirectory(
|
|
||||||
homePath,
|
|
||||||
{ name: "PersonalConfig" }
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
personalConfigArray.length > 0 &&
|
|
||||||
!directoryPath.startsWith(homePath)
|
|
||||||
) {
|
|
||||||
const lastElement =
|
|
||||||
personalConfigArray[personalConfigArray.length - 1];
|
|
||||||
|
|
||||||
emitDeprecationWarning(
|
|
||||||
lastElement.filePath,
|
|
||||||
"ESLINT_PERSONAL_CONFIG_LOAD"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
finalConfigArray = finalConfigArray.concat(personalConfigArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply CLI options.
|
|
||||||
if (cliConfigArray.length > 0) {
|
|
||||||
finalConfigArray = finalConfigArray.concat(cliConfigArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate rule settings and environments.
|
|
||||||
const validator = new ConfigValidator({
|
|
||||||
builtInRules
|
|
||||||
});
|
|
||||||
|
|
||||||
validator.validateConfigArray(finalConfigArray);
|
|
||||||
|
|
||||||
// Cache it.
|
|
||||||
Object.freeze(finalConfigArray);
|
|
||||||
finalizeCache.set(configArray, finalConfigArray);
|
|
||||||
|
|
||||||
debug(
|
|
||||||
"Configuration was determined: %o on %s",
|
|
||||||
finalConfigArray,
|
|
||||||
directoryPath
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// At least one element (the default ignore patterns) exists.
|
|
||||||
if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
|
|
||||||
throw new ConfigurationNotFoundError(directoryPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return finalConfigArray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module.exports = { CascadingConfigArrayFactory };
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,524 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview `ConfigArray` class.
|
|
||||||
*
|
|
||||||
* `ConfigArray` class expresses the full of a configuration. It has the entry
|
|
||||||
* config file, base config files that were extended, loaded parsers, and loaded
|
|
||||||
* plugins.
|
|
||||||
*
|
|
||||||
* `ConfigArray` class provides three properties and two methods.
|
|
||||||
*
|
|
||||||
* - `pluginEnvironments`
|
|
||||||
* - `pluginProcessors`
|
|
||||||
* - `pluginRules`
|
|
||||||
* The `Map` objects that contain the members of all plugins that this
|
|
||||||
* config array contains. Those map objects don't have mutation methods.
|
|
||||||
* Those keys are the member ID such as `pluginId/memberName`.
|
|
||||||
* - `isRoot()`
|
|
||||||
* If `true` then this configuration has `root:true` property.
|
|
||||||
* - `extractConfig(filePath)`
|
|
||||||
* Extract the final configuration for a given file. This means merging
|
|
||||||
* every config array element which that `criteria` property matched. The
|
|
||||||
* `filePath` argument must be an absolute path.
|
|
||||||
*
|
|
||||||
* `ConfigArrayFactory` provides the loading logic of config files.
|
|
||||||
*
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const { ExtractedConfig } = require("./extracted-config");
|
|
||||||
const { IgnorePattern } = require("./ignore-pattern");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Define types for VSCode IntelliSense.
|
|
||||||
/** @typedef {import("../../shared/types").Environment} Environment */
|
|
||||||
/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
|
|
||||||
/** @typedef {import("../../shared/types").RuleConf} RuleConf */
|
|
||||||
/** @typedef {import("../../shared/types").Rule} Rule */
|
|
||||||
/** @typedef {import("../../shared/types").Plugin} Plugin */
|
|
||||||
/** @typedef {import("../../shared/types").Processor} Processor */
|
|
||||||
/** @typedef {import("./config-dependency").DependentParser} DependentParser */
|
|
||||||
/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
|
|
||||||
/** @typedef {import("./override-tester")["OverrideTester"]} OverrideTester */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} ConfigArrayElement
|
|
||||||
* @property {string} name The name of this config element.
|
|
||||||
* @property {string} filePath The path to the source file of this config element.
|
|
||||||
* @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
|
|
||||||
* @property {Record<string, boolean>|undefined} env The environment settings.
|
|
||||||
* @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
|
|
||||||
* @property {IgnorePattern|undefined} ignorePattern The ignore patterns.
|
|
||||||
* @property {boolean|undefined} noInlineConfig The flag that disables directive comments.
|
|
||||||
* @property {DependentParser|undefined} parser The parser loader.
|
|
||||||
* @property {Object|undefined} parserOptions The parser options.
|
|
||||||
* @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
|
|
||||||
* @property {string|undefined} processor The processor name to refer plugin's processor.
|
|
||||||
* @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
|
|
||||||
* @property {boolean|undefined} root The flag to express root.
|
|
||||||
* @property {Record<string, RuleConf>|undefined} rules The rule settings
|
|
||||||
* @property {Object|undefined} settings The shared settings.
|
|
||||||
* @property {"config" | "ignore" | "implicit-processor"} type The element type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} ConfigArrayInternalSlots
|
|
||||||
* @property {Map<string, ExtractedConfig>} cache The cache to extract configs.
|
|
||||||
* @property {ReadonlyMap<string, Environment>|null} envMap The map from environment ID to environment definition.
|
|
||||||
* @property {ReadonlyMap<string, Processor>|null} processorMap The map from processor ID to environment definition.
|
|
||||||
* @property {ReadonlyMap<string, Rule>|null} ruleMap The map from rule ID to rule definition.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @type {WeakMap<ConfigArray, ConfigArrayInternalSlots>} */
|
|
||||||
const internalSlotsMap = new class extends WeakMap {
|
|
||||||
get(key) {
|
|
||||||
let value = super.get(key);
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
value = {
|
|
||||||
cache: new Map(),
|
|
||||||
envMap: null,
|
|
||||||
processorMap: null,
|
|
||||||
ruleMap: null
|
|
||||||
};
|
|
||||||
super.set(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the indices which are matched to a given file.
|
|
||||||
* @param {ConfigArrayElement[]} elements The elements.
|
|
||||||
* @param {string} filePath The path to a target file.
|
|
||||||
* @returns {number[]} The indices.
|
|
||||||
*/
|
|
||||||
function getMatchedIndices(elements, filePath) {
|
|
||||||
const indices = [];
|
|
||||||
|
|
||||||
for (let i = elements.length - 1; i >= 0; --i) {
|
|
||||||
const element = elements[i];
|
|
||||||
|
|
||||||
if (!element.criteria || (filePath && element.criteria.test(filePath))) {
|
|
||||||
indices.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return indices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a value is a non-null object.
|
|
||||||
* @param {any} x The value to check.
|
|
||||||
* @returns {boolean} `true` if the value is a non-null object.
|
|
||||||
*/
|
|
||||||
function isNonNullObject(x) {
|
|
||||||
return typeof x === "object" && x !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge two objects.
|
|
||||||
*
|
|
||||||
* Assign every property values of `y` to `x` if `x` doesn't have the property.
|
|
||||||
* If `x`'s property value is an object, it does recursive.
|
|
||||||
* @param {Object} target The destination to merge
|
|
||||||
* @param {Object|undefined} source The source to merge.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function mergeWithoutOverwrite(target, source) {
|
|
||||||
if (!isNonNullObject(source)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key of Object.keys(source)) {
|
|
||||||
if (key === "__proto__") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNonNullObject(target[key])) {
|
|
||||||
mergeWithoutOverwrite(target[key], source[key]);
|
|
||||||
} else if (target[key] === void 0) {
|
|
||||||
if (isNonNullObject(source[key])) {
|
|
||||||
target[key] = Array.isArray(source[key]) ? [] : {};
|
|
||||||
mergeWithoutOverwrite(target[key], source[key]);
|
|
||||||
} else if (source[key] !== void 0) {
|
|
||||||
target[key] = source[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The error for plugin conflicts.
|
|
||||||
*/
|
|
||||||
class PluginConflictError extends Error {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this error object.
|
|
||||||
* @param {string} pluginId The plugin ID.
|
|
||||||
* @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
|
|
||||||
*/
|
|
||||||
constructor(pluginId, plugins) {
|
|
||||||
super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
|
|
||||||
this.messageTemplate = "plugin-conflict";
|
|
||||||
this.messageData = { pluginId, plugins };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge plugins.
|
|
||||||
* `target`'s definition is prior to `source`'s.
|
|
||||||
* @param {Record<string, DependentPlugin>} target The destination to merge
|
|
||||||
* @param {Record<string, DependentPlugin>|undefined} source The source to merge.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function mergePlugins(target, source) {
|
|
||||||
if (!isNonNullObject(source)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key of Object.keys(source)) {
|
|
||||||
if (key === "__proto__") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const targetValue = target[key];
|
|
||||||
const sourceValue = source[key];
|
|
||||||
|
|
||||||
// Adopt the plugin which was found at first.
|
|
||||||
if (targetValue === void 0) {
|
|
||||||
if (sourceValue.error) {
|
|
||||||
throw sourceValue.error;
|
|
||||||
}
|
|
||||||
target[key] = sourceValue;
|
|
||||||
} else if (sourceValue.filePath !== targetValue.filePath) {
|
|
||||||
throw new PluginConflictError(key, [
|
|
||||||
{
|
|
||||||
filePath: targetValue.filePath,
|
|
||||||
importerName: targetValue.importerName
|
|
||||||
},
|
|
||||||
{
|
|
||||||
filePath: sourceValue.filePath,
|
|
||||||
importerName: sourceValue.importerName
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge rule configs.
|
|
||||||
* `target`'s definition is prior to `source`'s.
|
|
||||||
* @param {Record<string, Array>} target The destination to merge
|
|
||||||
* @param {Record<string, RuleConf>|undefined} source The source to merge.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function mergeRuleConfigs(target, source) {
|
|
||||||
if (!isNonNullObject(source)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key of Object.keys(source)) {
|
|
||||||
if (key === "__proto__") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const targetDef = target[key];
|
|
||||||
const sourceDef = source[key];
|
|
||||||
|
|
||||||
// Adopt the rule config which was found at first.
|
|
||||||
if (targetDef === void 0) {
|
|
||||||
if (Array.isArray(sourceDef)) {
|
|
||||||
target[key] = [...sourceDef];
|
|
||||||
} else {
|
|
||||||
target[key] = [sourceDef];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the first found rule config is severity only and the current rule
|
|
||||||
* config has options, merge the severity and the options.
|
|
||||||
*/
|
|
||||||
} else if (
|
|
||||||
targetDef.length === 1 &&
|
|
||||||
Array.isArray(sourceDef) &&
|
|
||||||
sourceDef.length >= 2
|
|
||||||
) {
|
|
||||||
targetDef.push(...sourceDef.slice(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the extracted config.
|
|
||||||
* @param {ConfigArray} instance The config elements.
|
|
||||||
* @param {number[]} indices The indices to use.
|
|
||||||
* @returns {ExtractedConfig} The extracted config.
|
|
||||||
*/
|
|
||||||
function createConfig(instance, indices) {
|
|
||||||
const config = new ExtractedConfig();
|
|
||||||
const ignorePatterns = [];
|
|
||||||
|
|
||||||
// Merge elements.
|
|
||||||
for (const index of indices) {
|
|
||||||
const element = instance[index];
|
|
||||||
|
|
||||||
// Adopt the parser which was found at first.
|
|
||||||
if (!config.parser && element.parser) {
|
|
||||||
if (element.parser.error) {
|
|
||||||
throw element.parser.error;
|
|
||||||
}
|
|
||||||
config.parser = element.parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adopt the processor which was found at first.
|
|
||||||
if (!config.processor && element.processor) {
|
|
||||||
config.processor = element.processor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adopt the noInlineConfig which was found at first.
|
|
||||||
if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {
|
|
||||||
config.noInlineConfig = element.noInlineConfig;
|
|
||||||
config.configNameOfNoInlineConfig = element.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adopt the reportUnusedDisableDirectives which was found at first.
|
|
||||||
if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {
|
|
||||||
config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect ignorePatterns
|
|
||||||
if (element.ignorePattern) {
|
|
||||||
ignorePatterns.push(element.ignorePattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge others.
|
|
||||||
mergeWithoutOverwrite(config.env, element.env);
|
|
||||||
mergeWithoutOverwrite(config.globals, element.globals);
|
|
||||||
mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
|
|
||||||
mergeWithoutOverwrite(config.settings, element.settings);
|
|
||||||
mergePlugins(config.plugins, element.plugins);
|
|
||||||
mergeRuleConfigs(config.rules, element.rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the predicate function for ignore patterns.
|
|
||||||
if (ignorePatterns.length > 0) {
|
|
||||||
config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect definitions.
|
|
||||||
* @template T, U
|
|
||||||
* @param {string} pluginId The plugin ID for prefix.
|
|
||||||
* @param {Record<string,T>} defs The definitions to collect.
|
|
||||||
* @param {Map<string, U>} map The map to output.
|
|
||||||
* @param {function(T): U} [normalize] The normalize function for each value.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function collect(pluginId, defs, map, normalize) {
|
|
||||||
if (defs) {
|
|
||||||
const prefix = pluginId && `${pluginId}/`;
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(defs)) {
|
|
||||||
map.set(
|
|
||||||
`${prefix}${key}`,
|
|
||||||
normalize ? normalize(value) : value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalize a rule definition.
|
|
||||||
* @param {Function|Rule} rule The rule definition to normalize.
|
|
||||||
* @returns {Rule} The normalized rule definition.
|
|
||||||
*/
|
|
||||||
function normalizePluginRule(rule) {
|
|
||||||
return typeof rule === "function" ? { create: rule } : rule;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the mutation methods from a given map.
|
|
||||||
* @param {Map<any, any>} map The map object to delete.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function deleteMutationMethods(map) {
|
|
||||||
Object.defineProperties(map, {
|
|
||||||
clear: { configurable: true, value: void 0 },
|
|
||||||
delete: { configurable: true, value: void 0 },
|
|
||||||
set: { configurable: true, value: void 0 }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
|
|
||||||
* @param {ConfigArrayElement[]} elements The config elements.
|
|
||||||
* @param {ConfigArrayInternalSlots} slots The internal slots.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function initPluginMemberMaps(elements, slots) {
|
|
||||||
const processed = new Set();
|
|
||||||
|
|
||||||
slots.envMap = new Map();
|
|
||||||
slots.processorMap = new Map();
|
|
||||||
slots.ruleMap = new Map();
|
|
||||||
|
|
||||||
for (const element of elements) {
|
|
||||||
if (!element.plugins) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [pluginId, value] of Object.entries(element.plugins)) {
|
|
||||||
const plugin = value.definition;
|
|
||||||
|
|
||||||
if (!plugin || processed.has(pluginId)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
processed.add(pluginId);
|
|
||||||
|
|
||||||
collect(pluginId, plugin.environments, slots.envMap);
|
|
||||||
collect(pluginId, plugin.processors, slots.processorMap);
|
|
||||||
collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteMutationMethods(slots.envMap);
|
|
||||||
deleteMutationMethods(slots.processorMap);
|
|
||||||
deleteMutationMethods(slots.ruleMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
|
|
||||||
* @param {ConfigArray} instance The config elements.
|
|
||||||
* @returns {ConfigArrayInternalSlots} The extracted config.
|
|
||||||
*/
|
|
||||||
function ensurePluginMemberMaps(instance) {
|
|
||||||
const slots = internalSlotsMap.get(instance);
|
|
||||||
|
|
||||||
if (!slots.ruleMap) {
|
|
||||||
initPluginMemberMaps(instance, slots);
|
|
||||||
}
|
|
||||||
|
|
||||||
return slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Config Array.
|
|
||||||
*
|
|
||||||
* `ConfigArray` instance contains all settings, parsers, and plugins.
|
|
||||||
* You need to call `ConfigArray#extractConfig(filePath)` method in order to
|
|
||||||
* extract, merge and get only the config data which is related to an arbitrary
|
|
||||||
* file.
|
|
||||||
* @extends {Array<ConfigArrayElement>}
|
|
||||||
*/
|
|
||||||
class ConfigArray extends Array {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the plugin environments.
|
|
||||||
* The returned map cannot be mutated.
|
|
||||||
* @type {ReadonlyMap<string, Environment>} The plugin environments.
|
|
||||||
*/
|
|
||||||
get pluginEnvironments() {
|
|
||||||
return ensurePluginMemberMaps(this).envMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the plugin processors.
|
|
||||||
* The returned map cannot be mutated.
|
|
||||||
* @type {ReadonlyMap<string, Processor>} The plugin processors.
|
|
||||||
*/
|
|
||||||
get pluginProcessors() {
|
|
||||||
return ensurePluginMemberMaps(this).processorMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the plugin rules.
|
|
||||||
* The returned map cannot be mutated.
|
|
||||||
* @returns {ReadonlyMap<string, Rule>} The plugin rules.
|
|
||||||
*/
|
|
||||||
get pluginRules() {
|
|
||||||
return ensurePluginMemberMaps(this).ruleMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this config has `root` flag.
|
|
||||||
* @returns {boolean} `true` if this config array is root.
|
|
||||||
*/
|
|
||||||
isRoot() {
|
|
||||||
for (let i = this.length - 1; i >= 0; --i) {
|
|
||||||
const root = this[i].root;
|
|
||||||
|
|
||||||
if (typeof root === "boolean") {
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the config data which is related to a given file.
|
|
||||||
* @param {string} filePath The absolute path to the target file.
|
|
||||||
* @returns {ExtractedConfig} The extracted config data.
|
|
||||||
*/
|
|
||||||
extractConfig(filePath) {
|
|
||||||
const { cache } = internalSlotsMap.get(this);
|
|
||||||
const indices = getMatchedIndices(this, filePath);
|
|
||||||
const cacheKey = indices.join(",");
|
|
||||||
|
|
||||||
if (!cache.has(cacheKey)) {
|
|
||||||
cache.set(cacheKey, createConfig(this, indices));
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache.get(cacheKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a given path is an additional lint target.
|
|
||||||
* @param {string} filePath The absolute path to the target file.
|
|
||||||
* @returns {boolean} `true` if the file is an additional lint target.
|
|
||||||
*/
|
|
||||||
isAdditionalTargetPath(filePath) {
|
|
||||||
for (const { criteria, type } of this) {
|
|
||||||
if (
|
|
||||||
type === "config" &&
|
|
||||||
criteria &&
|
|
||||||
!criteria.endsWithWildcard &&
|
|
||||||
criteria.test(filePath)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const exportObject = {
|
|
||||||
ConfigArray,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the used extracted configs.
|
|
||||||
* CLIEngine will use this method to collect used deprecated rules.
|
|
||||||
* @param {ConfigArray} instance The config array object to get.
|
|
||||||
* @returns {ExtractedConfig[]} The used extracted configs.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
getUsedExtractedConfigs(instance) {
|
|
||||||
const { cache } = internalSlotsMap.get(instance);
|
|
||||||
|
|
||||||
return Array.from(cache.values());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = exportObject;
|
|
|
@ -1,116 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview `ConfigDependency` class.
|
|
||||||
*
|
|
||||||
* `ConfigDependency` class expresses a loaded parser or plugin.
|
|
||||||
*
|
|
||||||
* If the parser or plugin was loaded successfully, it has `definition` property
|
|
||||||
* and `filePath` property. Otherwise, it has `error` property.
|
|
||||||
*
|
|
||||||
* When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it
|
|
||||||
* omits `definition` property.
|
|
||||||
*
|
|
||||||
* `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers
|
|
||||||
* or plugins.
|
|
||||||
*
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const util = require("util");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class is to store parsers or plugins.
|
|
||||||
* This class hides the loaded object from `JSON.stringify()` and `console.log`.
|
|
||||||
* @template T
|
|
||||||
*/
|
|
||||||
class ConfigDependency {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this instance.
|
|
||||||
* @param {Object} data The dependency data.
|
|
||||||
* @param {T} [data.definition] The dependency if the loading succeeded.
|
|
||||||
* @param {Error} [data.error] The error object if the loading failed.
|
|
||||||
* @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.
|
|
||||||
* @param {string} data.id The ID of this dependency.
|
|
||||||
* @param {string} data.importerName The name of the config file which loads this dependency.
|
|
||||||
* @param {string} data.importerPath The path to the config file which loads this dependency.
|
|
||||||
*/
|
|
||||||
constructor({
|
|
||||||
definition = null,
|
|
||||||
error = null,
|
|
||||||
filePath = null,
|
|
||||||
id,
|
|
||||||
importerName,
|
|
||||||
importerPath
|
|
||||||
}) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The loaded dependency if the loading succeeded.
|
|
||||||
* @type {T|null}
|
|
||||||
*/
|
|
||||||
this.definition = definition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The error object if the loading failed.
|
|
||||||
* @type {Error|null}
|
|
||||||
*/
|
|
||||||
this.error = error;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The loaded dependency if the loading succeeded.
|
|
||||||
* @type {string|null}
|
|
||||||
*/
|
|
||||||
this.filePath = filePath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ID of this dependency.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
this.id = id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the config file which loads this dependency.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
this.importerName = importerName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path to the config file which loads this dependency.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
this.importerPath = importerPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/require-description
|
|
||||||
/**
|
|
||||||
* @returns {Object} a JSON compatible object.
|
|
||||||
*/
|
|
||||||
toJSON() {
|
|
||||||
const obj = this[util.inspect.custom]();
|
|
||||||
|
|
||||||
// Display `error.message` (`Error#message` is unenumerable).
|
|
||||||
if (obj.error instanceof Error) {
|
|
||||||
obj.error = { ...obj.error, message: obj.error.message };
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/require-description
|
|
||||||
/**
|
|
||||||
* @returns {Object} an object to display by `console.log()`.
|
|
||||||
*/
|
|
||||||
[util.inspect.custom]() {
|
|
||||||
const {
|
|
||||||
definition: _ignore, // eslint-disable-line no-unused-vars
|
|
||||||
...obj
|
|
||||||
} = this;
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @typedef {ConfigDependency<import("../../shared/types").Parser>} DependentParser */
|
|
||||||
/** @typedef {ConfigDependency<import("../../shared/types").Plugin>} DependentPlugin */
|
|
||||||
|
|
||||||
module.exports = { ConfigDependency };
|
|
|
@ -1,146 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview `ExtractedConfig` class.
|
|
||||||
*
|
|
||||||
* `ExtractedConfig` class expresses a final configuration for a specific file.
|
|
||||||
*
|
|
||||||
* It provides one method.
|
|
||||||
*
|
|
||||||
* - `toCompatibleObjectAsConfigFileContent()`
|
|
||||||
* Convert this configuration to the compatible object as the content of
|
|
||||||
* config files. It converts the loaded parser and plugins to strings.
|
|
||||||
* `CLIEngine#getConfigForFile(filePath)` method uses this method.
|
|
||||||
*
|
|
||||||
* `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.
|
|
||||||
*
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { IgnorePattern } = require("./ignore-pattern");
|
|
||||||
|
|
||||||
// For VSCode intellisense
|
|
||||||
/** @typedef {import("../../shared/types").ConfigData} ConfigData */
|
|
||||||
/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
|
|
||||||
/** @typedef {import("../../shared/types").SeverityConf} SeverityConf */
|
|
||||||
/** @typedef {import("./config-dependency").DependentParser} DependentParser */
|
|
||||||
/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if `xs` starts with `ys`.
|
|
||||||
* @template T
|
|
||||||
* @param {T[]} xs The array to check.
|
|
||||||
* @param {T[]} ys The array that may be the first part of `xs`.
|
|
||||||
* @returns {boolean} `true` if `xs` starts with `ys`.
|
|
||||||
*/
|
|
||||||
function startsWith(xs, ys) {
|
|
||||||
return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class for extracted config data.
|
|
||||||
*/
|
|
||||||
class ExtractedConfig {
|
|
||||||
constructor() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The config name what `noInlineConfig` setting came from.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
this.configNameOfNoInlineConfig = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Environments.
|
|
||||||
* @type {Record<string, boolean>}
|
|
||||||
*/
|
|
||||||
this.env = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global variables.
|
|
||||||
* @type {Record<string, GlobalConf>}
|
|
||||||
*/
|
|
||||||
this.globals = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The glob patterns that ignore to lint.
|
|
||||||
* @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
|
|
||||||
*/
|
|
||||||
this.ignores = void 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The flag that disables directive comments.
|
|
||||||
* @type {boolean|undefined}
|
|
||||||
*/
|
|
||||||
this.noInlineConfig = void 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser definition.
|
|
||||||
* @type {DependentParser|null}
|
|
||||||
*/
|
|
||||||
this.parser = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for the parser.
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
this.parserOptions = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugin definitions.
|
|
||||||
* @type {Record<string, DependentPlugin>}
|
|
||||||
*/
|
|
||||||
this.plugins = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processor ID.
|
|
||||||
* @type {string|null}
|
|
||||||
*/
|
|
||||||
this.processor = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The flag that reports unused `eslint-disable` directive comments.
|
|
||||||
* @type {boolean|undefined}
|
|
||||||
*/
|
|
||||||
this.reportUnusedDisableDirectives = void 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rule settings.
|
|
||||||
* @type {Record<string, [SeverityConf, ...any[]]>}
|
|
||||||
*/
|
|
||||||
this.rules = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shared settings.
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
this.settings = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert this config to the compatible object as a config file content.
|
|
||||||
* @returns {ConfigData} The converted object.
|
|
||||||
*/
|
|
||||||
toCompatibleObjectAsConfigFileContent() {
|
|
||||||
const {
|
|
||||||
/* eslint-disable no-unused-vars */
|
|
||||||
configNameOfNoInlineConfig: _ignore1,
|
|
||||||
processor: _ignore2,
|
|
||||||
/* eslint-enable no-unused-vars */
|
|
||||||
ignores,
|
|
||||||
...config
|
|
||||||
} = this;
|
|
||||||
|
|
||||||
config.parser = config.parser && config.parser.filePath;
|
|
||||||
config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
|
|
||||||
config.ignorePatterns = ignores ? ignores.patterns : [];
|
|
||||||
|
|
||||||
// Strip the default patterns from `ignorePatterns`.
|
|
||||||
if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
|
|
||||||
config.ignorePatterns =
|
|
||||||
config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { ExtractedConfig };
|
|
|
@ -1,237 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview `IgnorePattern` class.
|
|
||||||
*
|
|
||||||
* `IgnorePattern` class has the set of glob patterns and the base path.
|
|
||||||
*
|
|
||||||
* It provides two static methods.
|
|
||||||
*
|
|
||||||
* - `IgnorePattern.createDefaultIgnore(cwd)`
|
|
||||||
* Create the default predicate function.
|
|
||||||
* - `IgnorePattern.createIgnore(ignorePatterns)`
|
|
||||||
* Create the predicate function from multiple `IgnorePattern` objects.
|
|
||||||
*
|
|
||||||
* It provides two properties and a method.
|
|
||||||
*
|
|
||||||
* - `patterns`
|
|
||||||
* The glob patterns that ignore to lint.
|
|
||||||
* - `basePath`
|
|
||||||
* The base path of the glob patterns. If absolute paths existed in the
|
|
||||||
* glob patterns, those are handled as relative paths to the base path.
|
|
||||||
* - `getPatternsRelativeTo(basePath)`
|
|
||||||
* Get `patterns` as modified for a given base path. It modifies the
|
|
||||||
* absolute paths in the patterns as prepending the difference of two base
|
|
||||||
* paths.
|
|
||||||
*
|
|
||||||
* `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
|
|
||||||
* `ignorePatterns` properties.
|
|
||||||
*
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const assert = require("assert");
|
|
||||||
const path = require("path");
|
|
||||||
const ignore = require("ignore");
|
|
||||||
const debug = require("debug")("eslintrc:ignore-pattern");
|
|
||||||
|
|
||||||
/** @typedef {ReturnType<import("ignore").default>} Ignore */
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the path to the common ancestor directory of given paths.
|
|
||||||
* @param {string[]} sourcePaths The paths to calculate the common ancestor.
|
|
||||||
* @returns {string} The path to the common ancestor directory.
|
|
||||||
*/
|
|
||||||
function getCommonAncestorPath(sourcePaths) {
|
|
||||||
let result = sourcePaths[0];
|
|
||||||
|
|
||||||
for (let i = 1; i < sourcePaths.length; ++i) {
|
|
||||||
const a = result;
|
|
||||||
const b = sourcePaths[i];
|
|
||||||
|
|
||||||
// Set the shorter one (it's the common ancestor if one includes the other).
|
|
||||||
result = a.length < b.length ? a : b;
|
|
||||||
|
|
||||||
// Set the common ancestor.
|
|
||||||
for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
|
|
||||||
if (a[j] !== b[j]) {
|
|
||||||
result = a.slice(0, lastSepPos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (a[j] === path.sep) {
|
|
||||||
lastSepPos = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let resolvedResult = result || path.sep;
|
|
||||||
|
|
||||||
// if Windows common ancestor is root of drive must have trailing slash to be absolute.
|
|
||||||
if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
|
|
||||||
resolvedResult += path.sep;
|
|
||||||
}
|
|
||||||
return resolvedResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make relative path.
|
|
||||||
* @param {string} from The source path to get relative path.
|
|
||||||
* @param {string} to The destination path to get relative path.
|
|
||||||
* @returns {string} The relative path.
|
|
||||||
*/
|
|
||||||
function relative(from, to) {
|
|
||||||
const relPath = path.relative(from, to);
|
|
||||||
|
|
||||||
if (path.sep === "/") {
|
|
||||||
return relPath;
|
|
||||||
}
|
|
||||||
return relPath.split(path.sep).join("/");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the trailing slash if existed.
|
|
||||||
* @param {string} filePath The path to check.
|
|
||||||
* @returns {string} The trailing slash if existed.
|
|
||||||
*/
|
|
||||||
function dirSuffix(filePath) {
|
|
||||||
const isDir = (
|
|
||||||
filePath.endsWith(path.sep) ||
|
|
||||||
(process.platform === "win32" && filePath.endsWith("/"))
|
|
||||||
);
|
|
||||||
|
|
||||||
return isDir ? "/" : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
|
|
||||||
const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class IgnorePattern {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default patterns.
|
|
||||||
* @type {string[]}
|
|
||||||
*/
|
|
||||||
static get DefaultPatterns() {
|
|
||||||
return DefaultPatterns;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the default predicate function.
|
|
||||||
* @param {string} cwd The current working directory.
|
|
||||||
* @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
|
|
||||||
* The preficate function.
|
|
||||||
* The first argument is an absolute path that is checked.
|
|
||||||
* The second argument is the flag to not ignore dotfiles.
|
|
||||||
* If the predicate function returned `true`, it means the path should be ignored.
|
|
||||||
*/
|
|
||||||
static createDefaultIgnore(cwd) {
|
|
||||||
return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the predicate function from multiple `IgnorePattern` objects.
|
|
||||||
* @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
|
|
||||||
* @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
|
|
||||||
* The preficate function.
|
|
||||||
* The first argument is an absolute path that is checked.
|
|
||||||
* The second argument is the flag to not ignore dotfiles.
|
|
||||||
* If the predicate function returned `true`, it means the path should be ignored.
|
|
||||||
*/
|
|
||||||
static createIgnore(ignorePatterns) {
|
|
||||||
debug("Create with: %o", ignorePatterns);
|
|
||||||
|
|
||||||
const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
|
|
||||||
const patterns = [].concat(
|
|
||||||
...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
|
|
||||||
);
|
|
||||||
const ig = ignore().add([...DotPatterns, ...patterns]);
|
|
||||||
const dotIg = ignore().add(patterns);
|
|
||||||
|
|
||||||
debug(" processed: %o", { basePath, patterns });
|
|
||||||
|
|
||||||
return Object.assign(
|
|
||||||
(filePath, dot = false) => {
|
|
||||||
assert(path.isAbsolute(filePath), "'filePath' should be an absolute path.");
|
|
||||||
const relPathRaw = relative(basePath, filePath);
|
|
||||||
const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
|
|
||||||
const adoptedIg = dot ? dotIg : ig;
|
|
||||||
const result = relPath !== "" && adoptedIg.ignores(relPath);
|
|
||||||
|
|
||||||
debug("Check", { filePath, dot, relativePath: relPath, result });
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
{ basePath, patterns }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a new `IgnorePattern` instance.
|
|
||||||
* @param {string[]} patterns The glob patterns that ignore to lint.
|
|
||||||
* @param {string} basePath The base path of `patterns`.
|
|
||||||
*/
|
|
||||||
constructor(patterns, basePath) {
|
|
||||||
assert(path.isAbsolute(basePath), "'basePath' should be an absolute path.");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The glob patterns that ignore to lint.
|
|
||||||
* @type {string[]}
|
|
||||||
*/
|
|
||||||
this.patterns = patterns;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base path of `patterns`.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
this.basePath = basePath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
|
|
||||||
*
|
|
||||||
* It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
|
|
||||||
* It's `false` as-is for `ignorePatterns` property in config files.
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
this.loose = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get `patterns` as modified for a given base path. It modifies the
|
|
||||||
* absolute paths in the patterns as prepending the difference of two base
|
|
||||||
* paths.
|
|
||||||
* @param {string} newBasePath The base path.
|
|
||||||
* @returns {string[]} Modifired patterns.
|
|
||||||
*/
|
|
||||||
getPatternsRelativeTo(newBasePath) {
|
|
||||||
assert(path.isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
|
|
||||||
const { basePath, loose, patterns } = this;
|
|
||||||
|
|
||||||
if (newBasePath === basePath) {
|
|
||||||
return patterns;
|
|
||||||
}
|
|
||||||
const prefix = `/${relative(newBasePath, basePath)}`;
|
|
||||||
|
|
||||||
return patterns.map(pattern => {
|
|
||||||
const negative = pattern.startsWith("!");
|
|
||||||
const head = negative ? "!" : "";
|
|
||||||
const body = negative ? pattern.slice(1) : pattern;
|
|
||||||
|
|
||||||
if (body.startsWith("/") || body.startsWith("../")) {
|
|
||||||
return `${head}${prefix}${body}`;
|
|
||||||
}
|
|
||||||
return loose ? pattern : `${head}${prefix}/**/${body}`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { IgnorePattern };
|
|
|
@ -1,20 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview `ConfigArray` class.
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { ConfigArray, getUsedExtractedConfigs } = require("./config-array");
|
|
||||||
const { ConfigDependency } = require("./config-dependency");
|
|
||||||
const { ExtractedConfig } = require("./extracted-config");
|
|
||||||
const { IgnorePattern } = require("./ignore-pattern");
|
|
||||||
const { OverrideTester } = require("./override-tester");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
ConfigArray,
|
|
||||||
ConfigDependency,
|
|
||||||
ExtractedConfig,
|
|
||||||
IgnorePattern,
|
|
||||||
OverrideTester,
|
|
||||||
getUsedExtractedConfigs
|
|
||||||
};
|
|
|
@ -1,223 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview `OverrideTester` class.
|
|
||||||
*
|
|
||||||
* `OverrideTester` class handles `files` property and `excludedFiles` property
|
|
||||||
* of `overrides` config.
|
|
||||||
*
|
|
||||||
* It provides one method.
|
|
||||||
*
|
|
||||||
* - `test(filePath)`
|
|
||||||
* Test if a file path matches the pair of `files` property and
|
|
||||||
* `excludedFiles` property. The `filePath` argument must be an absolute
|
|
||||||
* path.
|
|
||||||
*
|
|
||||||
* `ConfigArrayFactory` creates `OverrideTester` objects when it processes
|
|
||||||
* `overrides` properties.
|
|
||||||
*
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const assert = require("assert");
|
|
||||||
const path = require("path");
|
|
||||||
const util = require("util");
|
|
||||||
const { Minimatch } = require("minimatch");
|
|
||||||
const minimatchOpts = { dot: true, matchBase: true };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Pattern
|
|
||||||
* @property {InstanceType<Minimatch>[] | null} includes The positive matchers.
|
|
||||||
* @property {InstanceType<Minimatch>[] | null} excludes The negative matchers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalize a given pattern to an array.
|
|
||||||
* @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.
|
|
||||||
* @returns {string[]|null} Normalized patterns.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function normalizePatterns(patterns) {
|
|
||||||
if (Array.isArray(patterns)) {
|
|
||||||
return patterns.filter(Boolean);
|
|
||||||
}
|
|
||||||
if (typeof patterns === "string" && patterns) {
|
|
||||||
return [patterns];
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the matchers of given patterns.
|
|
||||||
* @param {string[]} patterns The patterns.
|
|
||||||
* @returns {InstanceType<Minimatch>[] | null} The matchers.
|
|
||||||
*/
|
|
||||||
function toMatcher(patterns) {
|
|
||||||
if (patterns.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return patterns.map(pattern => {
|
|
||||||
if (/^\.[/\\]/u.test(pattern)) {
|
|
||||||
return new Minimatch(
|
|
||||||
pattern.slice(2),
|
|
||||||
|
|
||||||
// `./*.js` should not match with `subdir/foo.js`
|
|
||||||
{ ...minimatchOpts, matchBase: false }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new Minimatch(pattern, minimatchOpts);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a given matcher to string.
|
|
||||||
* @param {Pattern} matchers The matchers.
|
|
||||||
* @returns {string} The string expression of the matcher.
|
|
||||||
*/
|
|
||||||
function patternToJson({ includes, excludes }) {
|
|
||||||
return {
|
|
||||||
includes: includes && includes.map(m => m.pattern),
|
|
||||||
excludes: excludes && excludes.map(m => m.pattern)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class to test given paths are matched by the patterns.
|
|
||||||
*/
|
|
||||||
class OverrideTester {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a tester with given criteria.
|
|
||||||
* If there are no criteria, returns `null`.
|
|
||||||
* @param {string|string[]} files The glob patterns for included files.
|
|
||||||
* @param {string|string[]} excludedFiles The glob patterns for excluded files.
|
|
||||||
* @param {string} basePath The path to the base directory to test paths.
|
|
||||||
* @returns {OverrideTester|null} The created instance or `null`.
|
|
||||||
*/
|
|
||||||
static create(files, excludedFiles, basePath) {
|
|
||||||
const includePatterns = normalizePatterns(files);
|
|
||||||
const excludePatterns = normalizePatterns(excludedFiles);
|
|
||||||
let endsWithWildcard = false;
|
|
||||||
|
|
||||||
if (includePatterns.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rejects absolute paths or relative paths to parents.
|
|
||||||
for (const pattern of includePatterns) {
|
|
||||||
if (path.isAbsolute(pattern) || pattern.includes("..")) {
|
|
||||||
throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
|
|
||||||
}
|
|
||||||
if (pattern.endsWith("*")) {
|
|
||||||
endsWithWildcard = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const pattern of excludePatterns) {
|
|
||||||
if (path.isAbsolute(pattern) || pattern.includes("..")) {
|
|
||||||
throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const includes = toMatcher(includePatterns);
|
|
||||||
const excludes = toMatcher(excludePatterns);
|
|
||||||
|
|
||||||
return new OverrideTester(
|
|
||||||
[{ includes, excludes }],
|
|
||||||
basePath,
|
|
||||||
endsWithWildcard
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Combine two testers by logical and.
|
|
||||||
* If either of the testers was `null`, returns the other tester.
|
|
||||||
* The `basePath` property of the two must be the same value.
|
|
||||||
* @param {OverrideTester|null} a A tester.
|
|
||||||
* @param {OverrideTester|null} b Another tester.
|
|
||||||
* @returns {OverrideTester|null} Combined tester.
|
|
||||||
*/
|
|
||||||
static and(a, b) {
|
|
||||||
if (!b) {
|
|
||||||
return a && new OverrideTester(
|
|
||||||
a.patterns,
|
|
||||||
a.basePath,
|
|
||||||
a.endsWithWildcard
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!a) {
|
|
||||||
return new OverrideTester(
|
|
||||||
b.patterns,
|
|
||||||
b.basePath,
|
|
||||||
b.endsWithWildcard
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.strictEqual(a.basePath, b.basePath);
|
|
||||||
return new OverrideTester(
|
|
||||||
a.patterns.concat(b.patterns),
|
|
||||||
a.basePath,
|
|
||||||
a.endsWithWildcard || b.endsWithWildcard
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this instance.
|
|
||||||
* @param {Pattern[]} patterns The matchers.
|
|
||||||
* @param {string} basePath The base path.
|
|
||||||
* @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
|
|
||||||
*/
|
|
||||||
constructor(patterns, basePath, endsWithWildcard = false) {
|
|
||||||
|
|
||||||
/** @type {Pattern[]} */
|
|
||||||
this.patterns = patterns;
|
|
||||||
|
|
||||||
/** @type {string} */
|
|
||||||
this.basePath = basePath;
|
|
||||||
|
|
||||||
/** @type {boolean} */
|
|
||||||
this.endsWithWildcard = endsWithWildcard;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if a given path is matched or not.
|
|
||||||
* @param {string} filePath The absolute path to the target file.
|
|
||||||
* @returns {boolean} `true` if the path was matched.
|
|
||||||
*/
|
|
||||||
test(filePath) {
|
|
||||||
if (typeof filePath !== "string" || !path.isAbsolute(filePath)) {
|
|
||||||
throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);
|
|
||||||
}
|
|
||||||
const relativePath = path.relative(this.basePath, filePath);
|
|
||||||
|
|
||||||
return this.patterns.every(({ includes, excludes }) => (
|
|
||||||
(!includes || includes.some(m => m.match(relativePath))) &&
|
|
||||||
(!excludes || !excludes.some(m => m.match(relativePath)))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/require-description
|
|
||||||
/**
|
|
||||||
* @returns {Object} a JSON compatible object.
|
|
||||||
*/
|
|
||||||
toJSON() {
|
|
||||||
if (this.patterns.length === 1) {
|
|
||||||
return {
|
|
||||||
...patternToJson(this.patterns[0]),
|
|
||||||
basePath: this.basePath
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
AND: this.patterns.map(patternToJson),
|
|
||||||
basePath: this.basePath
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line jsdoc/require-description
|
|
||||||
/**
|
|
||||||
* @returns {Object} an object to display by `console.log()`.
|
|
||||||
*/
|
|
||||||
[util.inspect.custom]() {
|
|
||||||
return this.toJSON();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { OverrideTester };
|
|
|
@ -1,308 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Compatibility class for flat config.
|
|
||||||
* @author Nicholas C. Zakas
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const path = require("path");
|
|
||||||
const environments = require("../conf/environments");
|
|
||||||
const createDebug = require("debug");
|
|
||||||
const { ConfigArrayFactory } = require("./config-array-factory");
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** @typedef {import("../../shared/types").Environment} Environment */
|
|
||||||
/** @typedef {import("../../shared/types").Processor} Processor */
|
|
||||||
|
|
||||||
const debug = createDebug("eslintrc:flat-compat");
|
|
||||||
const cafactory = Symbol("cafactory");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates an ESLintRC-style config object into a flag-config-style config
|
|
||||||
* object.
|
|
||||||
* @param {Object} eslintrcConfig An ESLintRC-style config object.
|
|
||||||
* @param {Object} options Options to help translate the config.
|
|
||||||
* @param {string} options.resolveConfigRelativeTo To the directory to resolve
|
|
||||||
* configs from.
|
|
||||||
* @param {string} options.resolvePluginsRelativeTo The directory to resolve
|
|
||||||
* plugins from.
|
|
||||||
* @param {ReadOnlyMap<string,Environment>} options.pluginEnvironments A map of plugin environment
|
|
||||||
* names to objects.
|
|
||||||
* @param {ReadOnlyMap<string,Processor>} options.pluginProcessors A map of plugin processor
|
|
||||||
* names to objects.
|
|
||||||
* @returns {Object} A flag-config-style config object.
|
|
||||||
*/
|
|
||||||
function translateESLintRC(eslintrcConfig, {
|
|
||||||
resolveConfigRelativeTo,
|
|
||||||
resolvePluginsRelativeTo,
|
|
||||||
pluginEnvironments,
|
|
||||||
pluginProcessors
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const flatConfig = {};
|
|
||||||
const configs = [];
|
|
||||||
const languageOptions = {};
|
|
||||||
const linterOptions = {};
|
|
||||||
const keysToCopy = ["settings", "rules", "processor"];
|
|
||||||
const languageOptionsKeysToCopy = ["globals", "parser", "parserOptions"];
|
|
||||||
const linterOptionsKeysToCopy = ["noInlineConfig", "reportUnusedDisableDirectives"];
|
|
||||||
|
|
||||||
// check for special settings for eslint:all and eslint:recommended:
|
|
||||||
if (eslintrcConfig.settings) {
|
|
||||||
if (eslintrcConfig.settings["eslint:all"] === true) {
|
|
||||||
return ["eslint:all"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eslintrcConfig.settings["eslint:recommended"] === true) {
|
|
||||||
return ["eslint:recommended"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy over simple translations
|
|
||||||
for (const key of keysToCopy) {
|
|
||||||
if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
|
|
||||||
flatConfig[key] = eslintrcConfig[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy over languageOptions
|
|
||||||
for (const key of languageOptionsKeysToCopy) {
|
|
||||||
if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
|
|
||||||
|
|
||||||
// create the languageOptions key in the flat config
|
|
||||||
flatConfig.languageOptions = languageOptions;
|
|
||||||
|
|
||||||
if (key === "parser") {
|
|
||||||
debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);
|
|
||||||
|
|
||||||
if (eslintrcConfig[key].error) {
|
|
||||||
throw eslintrcConfig[key].error;
|
|
||||||
}
|
|
||||||
|
|
||||||
languageOptions[key] = eslintrcConfig[key].definition;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clone any object values that are in the eslintrc config
|
|
||||||
if (eslintrcConfig[key] && typeof eslintrcConfig[key] === "object") {
|
|
||||||
languageOptions[key] = {
|
|
||||||
...eslintrcConfig[key]
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
languageOptions[key] = eslintrcConfig[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy over linterOptions
|
|
||||||
for (const key of linterOptionsKeysToCopy) {
|
|
||||||
if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
|
|
||||||
flatConfig.linterOptions = linterOptions;
|
|
||||||
linterOptions[key] = eslintrcConfig[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// move ecmaVersion a level up
|
|
||||||
if (languageOptions.parserOptions) {
|
|
||||||
|
|
||||||
if ("ecmaVersion" in languageOptions.parserOptions) {
|
|
||||||
languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;
|
|
||||||
delete languageOptions.parserOptions.ecmaVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("sourceType" in languageOptions.parserOptions) {
|
|
||||||
languageOptions.sourceType = languageOptions.parserOptions.sourceType;
|
|
||||||
delete languageOptions.parserOptions.sourceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if we even need parserOptions anymore and remove it if not
|
|
||||||
if (Object.keys(languageOptions.parserOptions).length === 0) {
|
|
||||||
delete languageOptions.parserOptions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// overrides
|
|
||||||
if (eslintrcConfig.criteria) {
|
|
||||||
flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate plugins
|
|
||||||
if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === "object") {
|
|
||||||
debug(`Translating plugins: ${eslintrcConfig.plugins}`);
|
|
||||||
|
|
||||||
flatConfig.plugins = {};
|
|
||||||
|
|
||||||
for (const pluginName of Object.keys(eslintrcConfig.plugins)) {
|
|
||||||
|
|
||||||
debug(`Translating plugin: ${pluginName}`);
|
|
||||||
debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);
|
|
||||||
|
|
||||||
const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
flatConfig.plugins[pluginName] = plugin;
|
|
||||||
|
|
||||||
// create a config for any processors
|
|
||||||
if (plugin.processors) {
|
|
||||||
for (const processorName of Object.keys(plugin.processors)) {
|
|
||||||
if (processorName.startsWith(".")) {
|
|
||||||
debug(`Assigning processor: ${pluginName}/${processorName}`);
|
|
||||||
|
|
||||||
configs.unshift({
|
|
||||||
files: [`**/*${processorName}`],
|
|
||||||
processor: pluginProcessors.get(`${pluginName}/${processorName}`)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate env - must come after plugins
|
|
||||||
if (eslintrcConfig.env && typeof eslintrcConfig.env === "object") {
|
|
||||||
for (const envName of Object.keys(eslintrcConfig.env)) {
|
|
||||||
|
|
||||||
// only add environments that are true
|
|
||||||
if (eslintrcConfig.env[envName]) {
|
|
||||||
debug(`Translating environment: ${envName}`);
|
|
||||||
|
|
||||||
if (environments.has(envName)) {
|
|
||||||
|
|
||||||
// built-in environments should be defined first
|
|
||||||
configs.unshift(...translateESLintRC(environments.get(envName), {
|
|
||||||
resolveConfigRelativeTo,
|
|
||||||
resolvePluginsRelativeTo
|
|
||||||
}));
|
|
||||||
} else if (pluginEnvironments.has(envName)) {
|
|
||||||
|
|
||||||
// if the environment comes from a plugin, it should come after the plugin config
|
|
||||||
configs.push(...translateESLintRC(pluginEnvironments.get(envName), {
|
|
||||||
resolveConfigRelativeTo,
|
|
||||||
resolvePluginsRelativeTo
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only add if there are actually keys in the config
|
|
||||||
if (Object.keys(flatConfig).length > 0) {
|
|
||||||
configs.push(flatConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
return configs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Exports
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A compatibility class for working with configs.
|
|
||||||
*/
|
|
||||||
class FlatCompat {
|
|
||||||
|
|
||||||
constructor({
|
|
||||||
baseDirectory = process.cwd(),
|
|
||||||
resolvePluginsRelativeTo = baseDirectory
|
|
||||||
} = {}) {
|
|
||||||
this.baseDirectory = baseDirectory;
|
|
||||||
this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
|
|
||||||
this[cafactory] = new ConfigArrayFactory({
|
|
||||||
cwd: baseDirectory,
|
|
||||||
resolvePluginsRelativeTo,
|
|
||||||
eslintAllPath: path.resolve(__dirname, "../conf/eslint-all.js"),
|
|
||||||
eslintRecommendedPath: path.resolve(__dirname, "../conf/eslint-recommended.js")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates an ESLintRC-style config into a flag-config-style config.
|
|
||||||
* @param {Object} eslintrcConfig The ESLintRC-style config object.
|
|
||||||
* @returns {Object} A flag-config-style config object.
|
|
||||||
*/
|
|
||||||
config(eslintrcConfig) {
|
|
||||||
const eslintrcArray = this[cafactory].create(eslintrcConfig, {
|
|
||||||
basePath: this.baseDirectory
|
|
||||||
});
|
|
||||||
|
|
||||||
const flatArray = [];
|
|
||||||
let hasIgnorePatterns = false;
|
|
||||||
|
|
||||||
eslintrcArray.forEach(configData => {
|
|
||||||
if (configData.type === "config") {
|
|
||||||
hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;
|
|
||||||
flatArray.push(...translateESLintRC(configData, {
|
|
||||||
resolveConfigRelativeTo: path.join(this.baseDirectory, "__placeholder.js"),
|
|
||||||
resolvePluginsRelativeTo: path.join(this.resolvePluginsRelativeTo, "__placeholder.js"),
|
|
||||||
pluginEnvironments: eslintrcArray.pluginEnvironments,
|
|
||||||
pluginProcessors: eslintrcArray.pluginProcessors
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// combine ignorePatterns to emulate ESLintRC behavior better
|
|
||||||
if (hasIgnorePatterns) {
|
|
||||||
flatArray.unshift({
|
|
||||||
ignores: [filePath => {
|
|
||||||
|
|
||||||
// Compute the final config for this file.
|
|
||||||
// This filters config array elements by `files`/`excludedFiles` then merges the elements.
|
|
||||||
const finalConfig = eslintrcArray.extractConfig(filePath);
|
|
||||||
|
|
||||||
// Test the `ignorePattern` properties of the final config.
|
|
||||||
return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return flatArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the `env` section of an ESLintRC-style config.
|
|
||||||
* @param {Object} envConfig The `env` section of an ESLintRC config.
|
|
||||||
* @returns {Object} A flag-config object representing the environments.
|
|
||||||
*/
|
|
||||||
env(envConfig) {
|
|
||||||
return this.config({
|
|
||||||
env: envConfig
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the `extends` section of an ESLintRC-style config.
|
|
||||||
* @param {...string} configsToExtend The names of the configs to load.
|
|
||||||
* @returns {Object} A flag-config object representing the config.
|
|
||||||
*/
|
|
||||||
extends(...configsToExtend) {
|
|
||||||
return this.config({
|
|
||||||
extends: configsToExtend
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the `plugins` section of an ESLintRC-style config.
|
|
||||||
* @param {...string} plugins The names of the plugins to load.
|
|
||||||
* @returns {Object} A flag-config object representing the plugins.
|
|
||||||
*/
|
|
||||||
plugins(...plugins) {
|
|
||||||
return this.config({
|
|
||||||
plugins
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.FlatCompat = FlatCompat;
|
|
|
@ -1,54 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Package exports for @eslint/eslintrc
|
|
||||||
* @author Nicholas C. Zakas
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const {
|
|
||||||
ConfigArrayFactory,
|
|
||||||
createContext: createConfigArrayFactoryContext
|
|
||||||
} = require("./config-array-factory");
|
|
||||||
|
|
||||||
const { CascadingConfigArrayFactory } = require("./cascading-config-array-factory");
|
|
||||||
const ModuleResolver = require("./shared/relative-module-resolver");
|
|
||||||
const { ConfigArray, getUsedExtractedConfigs } = require("./config-array");
|
|
||||||
const { ConfigDependency } = require("./config-array/config-dependency");
|
|
||||||
const { ExtractedConfig } = require("./config-array/extracted-config");
|
|
||||||
const { IgnorePattern } = require("./config-array/ignore-pattern");
|
|
||||||
const { OverrideTester } = require("./config-array/override-tester");
|
|
||||||
const ConfigOps = require("./shared/config-ops");
|
|
||||||
const ConfigValidator = require("./shared/config-validator");
|
|
||||||
const naming = require("./shared/naming");
|
|
||||||
const { FlatCompat } = require("./flat-compat");
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Exports
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
|
|
||||||
Legacy: {
|
|
||||||
ConfigArray,
|
|
||||||
createConfigArrayFactoryContext,
|
|
||||||
CascadingConfigArrayFactory,
|
|
||||||
ConfigArrayFactory,
|
|
||||||
ConfigDependency,
|
|
||||||
ExtractedConfig,
|
|
||||||
IgnorePattern,
|
|
||||||
OverrideTester,
|
|
||||||
getUsedExtractedConfigs,
|
|
||||||
|
|
||||||
// shared
|
|
||||||
ConfigOps,
|
|
||||||
ConfigValidator,
|
|
||||||
ModuleResolver,
|
|
||||||
naming
|
|
||||||
},
|
|
||||||
|
|
||||||
FlatCompat
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,34 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview The instance of Ajv validator.
|
|
||||||
* @author Evgeny Poberezkin
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const Ajv = require("ajv"),
|
|
||||||
metaSchema = require("ajv/lib/refs/json-schema-draft-04.json");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module.exports = (additionalOptions = {}) => {
|
|
||||||
const ajv = new Ajv({
|
|
||||||
meta: false,
|
|
||||||
useDefaults: true,
|
|
||||||
validateSchema: false,
|
|
||||||
missingRefs: "ignore",
|
|
||||||
verbose: true,
|
|
||||||
schemaId: "auto",
|
|
||||||
...additionalOptions
|
|
||||||
});
|
|
||||||
|
|
||||||
ajv.addMetaSchema(metaSchema);
|
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
|
||||||
ajv._opts.defaultMeta = metaSchema.id;
|
|
||||||
|
|
||||||
return ajv;
|
|
||||||
};
|
|
|
@ -1,130 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Config file operations. This file must be usable in the browser,
|
|
||||||
* so no Node-specific code can be here.
|
|
||||||
* @author Nicholas C. Zakas
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Private
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
|
|
||||||
RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {
|
|
||||||
map[value] = index;
|
|
||||||
return map;
|
|
||||||
}, {}),
|
|
||||||
VALID_SEVERITIES = [0, 1, 2, "off", "warn", "error"];
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalizes the severity value of a rule's configuration to a number
|
|
||||||
* @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
|
|
||||||
* received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
|
|
||||||
* the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
|
|
||||||
* whose first element is one of the above values. Strings are matched case-insensitively.
|
|
||||||
* @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
|
|
||||||
*/
|
|
||||||
getRuleSeverity(ruleConfig) {
|
|
||||||
const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
|
||||||
|
|
||||||
if (severityValue === 0 || severityValue === 1 || severityValue === 2) {
|
|
||||||
return severityValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof severityValue === "string") {
|
|
||||||
return RULE_SEVERITY[severityValue.toLowerCase()] || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts old-style severity settings (0, 1, 2) into new-style
|
|
||||||
* severity settings (off, warn, error) for all rules. Assumption is that severity
|
|
||||||
* values have already been validated as correct.
|
|
||||||
* @param {Object} config The config object to normalize.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
normalizeToStrings(config) {
|
|
||||||
|
|
||||||
if (config.rules) {
|
|
||||||
Object.keys(config.rules).forEach(ruleId => {
|
|
||||||
const ruleConfig = config.rules[ruleId];
|
|
||||||
|
|
||||||
if (typeof ruleConfig === "number") {
|
|
||||||
config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];
|
|
||||||
} else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "number") {
|
|
||||||
ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if the severity for the given rule configuration represents an error.
|
|
||||||
* @param {int|string|Array} ruleConfig The configuration for an individual rule.
|
|
||||||
* @returns {boolean} True if the rule represents an error, false if not.
|
|
||||||
*/
|
|
||||||
isErrorSeverity(ruleConfig) {
|
|
||||||
return module.exports.getRuleSeverity(ruleConfig) === 2;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether a given config has valid severity or not.
|
|
||||||
* @param {number|string|Array} ruleConfig The configuration for an individual rule.
|
|
||||||
* @returns {boolean} `true` if the configuration has valid severity.
|
|
||||||
*/
|
|
||||||
isValidSeverity(ruleConfig) {
|
|
||||||
let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
|
||||||
|
|
||||||
if (typeof severity === "string") {
|
|
||||||
severity = severity.toLowerCase();
|
|
||||||
}
|
|
||||||
return VALID_SEVERITIES.indexOf(severity) !== -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether every rule of a given config has valid severity or not.
|
|
||||||
* @param {Object} config The configuration for rules.
|
|
||||||
* @returns {boolean} `true` if the configuration has valid severity.
|
|
||||||
*/
|
|
||||||
isEverySeverityValid(config) {
|
|
||||||
return Object.keys(config).every(ruleId => this.isValidSeverity(config[ruleId]));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalizes a value for a global in a config
|
|
||||||
* @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
|
|
||||||
* a global directive comment
|
|
||||||
* @returns {("readable"|"writeable"|"off")} The value normalized as a string
|
|
||||||
* @throws Error if global value is invalid
|
|
||||||
*/
|
|
||||||
normalizeConfigGlobal(configuredValue) {
|
|
||||||
switch (configuredValue) {
|
|
||||||
case "off":
|
|
||||||
return "off";
|
|
||||||
|
|
||||||
case true:
|
|
||||||
case "true":
|
|
||||||
case "writeable":
|
|
||||||
case "writable":
|
|
||||||
return "writable";
|
|
||||||
|
|
||||||
case null:
|
|
||||||
case false:
|
|
||||||
case "false":
|
|
||||||
case "readable":
|
|
||||||
case "readonly":
|
|
||||||
return "readonly";
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,326 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Validates configs.
|
|
||||||
* @author Brandon Mills
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/* eslint class-methods-use-this: "off" */
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const
|
|
||||||
util = require("util"),
|
|
||||||
configSchema = require("../../conf/config-schema"),
|
|
||||||
BuiltInEnvironments = require("../../conf/environments"),
|
|
||||||
ConfigOps = require("./config-ops"),
|
|
||||||
{ emitDeprecationWarning } = require("./deprecation-warnings");
|
|
||||||
|
|
||||||
const ajv = require("./ajv")();
|
|
||||||
const ruleValidators = new WeakMap();
|
|
||||||
const noop = Function.prototype;
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Private
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
let validateSchema;
|
|
||||||
const severityMap = {
|
|
||||||
error: 2,
|
|
||||||
warn: 1,
|
|
||||||
off: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
const validated = new WeakSet();
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Exports
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module.exports = class ConfigValidator {
|
|
||||||
constructor({ builtInRules = new Map() } = {}) {
|
|
||||||
this.builtInRules = builtInRules;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a complete options schema for a rule.
|
|
||||||
* @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
|
|
||||||
* @returns {Object} JSON Schema for the rule's options.
|
|
||||||
*/
|
|
||||||
getRuleOptionsSchema(rule) {
|
|
||||||
if (!rule) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const schema = rule.schema || rule.meta && rule.meta.schema;
|
|
||||||
|
|
||||||
// Given a tuple of schemas, insert warning level at the beginning
|
|
||||||
if (Array.isArray(schema)) {
|
|
||||||
if (schema.length) {
|
|
||||||
return {
|
|
||||||
type: "array",
|
|
||||||
items: schema,
|
|
||||||
minItems: 0,
|
|
||||||
maxItems: schema.length
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: "array",
|
|
||||||
minItems: 0,
|
|
||||||
maxItems: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a full schema, leave it alone
|
|
||||||
return schema || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.
|
|
||||||
* @param {options} options The given options for the rule.
|
|
||||||
* @returns {number|string} The rule's severity value
|
|
||||||
*/
|
|
||||||
validateRuleSeverity(options) {
|
|
||||||
const severity = Array.isArray(options) ? options[0] : options;
|
|
||||||
const normSeverity = typeof severity === "string" ? severityMap[severity.toLowerCase()] : severity;
|
|
||||||
|
|
||||||
if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {
|
|
||||||
return normSeverity;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/gu, "\"").replace(/\n/gu, "")}').\n`);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the non-severity options passed to a rule, based on its schema.
|
|
||||||
* @param {{create: Function}} rule The rule to validate
|
|
||||||
* @param {Array} localOptions The options for the rule, excluding severity
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateRuleSchema(rule, localOptions) {
|
|
||||||
if (!ruleValidators.has(rule)) {
|
|
||||||
const schema = this.getRuleOptionsSchema(rule);
|
|
||||||
|
|
||||||
if (schema) {
|
|
||||||
ruleValidators.set(rule, ajv.compile(schema));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const validateRule = ruleValidators.get(rule);
|
|
||||||
|
|
||||||
if (validateRule) {
|
|
||||||
validateRule(localOptions);
|
|
||||||
if (validateRule.errors) {
|
|
||||||
throw new Error(validateRule.errors.map(
|
|
||||||
error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`
|
|
||||||
).join(""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a rule's options against its schema.
|
|
||||||
* @param {{create: Function}|null} rule The rule that the config is being validated for
|
|
||||||
* @param {string} ruleId The rule's unique name.
|
|
||||||
* @param {Array|number} options The given options for the rule.
|
|
||||||
* @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,
|
|
||||||
* no source is prepended to the message.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateRuleOptions(rule, ruleId, options, source = null) {
|
|
||||||
try {
|
|
||||||
const severity = this.validateRuleSeverity(options);
|
|
||||||
|
|
||||||
if (severity !== 0) {
|
|
||||||
this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
const enhancedMessage = `Configuration for rule "${ruleId}" is invalid:\n${err.message}`;
|
|
||||||
|
|
||||||
if (typeof source === "string") {
|
|
||||||
throw new Error(`${source}:\n\t${enhancedMessage}`);
|
|
||||||
} else {
|
|
||||||
throw new Error(enhancedMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates an environment object
|
|
||||||
* @param {Object} environment The environment config object to validate.
|
|
||||||
* @param {string} source The name of the configuration source to report in any errors.
|
|
||||||
* @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateEnvironment(
|
|
||||||
environment,
|
|
||||||
source,
|
|
||||||
getAdditionalEnv = noop
|
|
||||||
) {
|
|
||||||
|
|
||||||
// not having an environment is ok
|
|
||||||
if (!environment) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(environment).forEach(id => {
|
|
||||||
const env = getAdditionalEnv(id) || BuiltInEnvironments.get(id) || null;
|
|
||||||
|
|
||||||
if (!env) {
|
|
||||||
const message = `${source}:\n\tEnvironment key "${id}" is unknown\n`;
|
|
||||||
|
|
||||||
throw new Error(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a rules config object
|
|
||||||
* @param {Object} rulesConfig The rules config object to validate.
|
|
||||||
* @param {string} source The name of the configuration source to report in any errors.
|
|
||||||
* @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateRules(
|
|
||||||
rulesConfig,
|
|
||||||
source,
|
|
||||||
getAdditionalRule = noop
|
|
||||||
) {
|
|
||||||
if (!rulesConfig) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(rulesConfig).forEach(id => {
|
|
||||||
const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;
|
|
||||||
|
|
||||||
this.validateRuleOptions(rule, id, rulesConfig[id], source);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a `globals` section of a config file
|
|
||||||
* @param {Object} globalsConfig The `globals` section
|
|
||||||
* @param {string|null} source The name of the configuration source to report in the event of an error.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateGlobals(globalsConfig, source = null) {
|
|
||||||
if (!globalsConfig) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.entries(globalsConfig)
|
|
||||||
.forEach(([configuredGlobal, configuredValue]) => {
|
|
||||||
try {
|
|
||||||
ConfigOps.normalizeConfigGlobal(configuredValue);
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\n${err.message}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate `processor` configuration.
|
|
||||||
* @param {string|undefined} processorName The processor name.
|
|
||||||
* @param {string} source The name of config file.
|
|
||||||
* @param {function(id:string): Processor} getProcessor The getter of defined processors.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateProcessor(processorName, source, getProcessor) {
|
|
||||||
if (processorName && !getProcessor(processorName)) {
|
|
||||||
throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats an array of schema validation errors.
|
|
||||||
* @param {Array} errors An array of error messages to format.
|
|
||||||
* @returns {string} Formatted error message
|
|
||||||
*/
|
|
||||||
formatErrors(errors) {
|
|
||||||
return errors.map(error => {
|
|
||||||
if (error.keyword === "additionalProperties") {
|
|
||||||
const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;
|
|
||||||
|
|
||||||
return `Unexpected top-level property "${formattedPropertyPath}"`;
|
|
||||||
}
|
|
||||||
if (error.keyword === "type") {
|
|
||||||
const formattedField = error.dataPath.slice(1);
|
|
||||||
const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join("/") : error.schema;
|
|
||||||
const formattedValue = JSON.stringify(error.data);
|
|
||||||
|
|
||||||
return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const field = error.dataPath[0] === "." ? error.dataPath.slice(1) : error.dataPath;
|
|
||||||
|
|
||||||
return `"${field}" ${error.message}. Value: ${JSON.stringify(error.data)}`;
|
|
||||||
}).map(message => `\t- ${message}.\n`).join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the top level properties of the config object.
|
|
||||||
* @param {Object} config The config object to validate.
|
|
||||||
* @param {string} source The name of the configuration source to report in any errors.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateConfigSchema(config, source = null) {
|
|
||||||
validateSchema = validateSchema || ajv.compile(configSchema);
|
|
||||||
|
|
||||||
if (!validateSchema(config)) {
|
|
||||||
throw new Error(`ESLint configuration in ${source} is invalid:\n${this.formatErrors(validateSchema.errors)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.hasOwnProperty.call(config, "ecmaFeatures")) {
|
|
||||||
emitDeprecationWarning(source, "ESLINT_LEGACY_ECMAFEATURES");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates an entire config object.
|
|
||||||
* @param {Object} config The config object to validate.
|
|
||||||
* @param {string} source The name of the configuration source to report in any errors.
|
|
||||||
* @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.
|
|
||||||
* @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validate(config, source, getAdditionalRule, getAdditionalEnv) {
|
|
||||||
this.validateConfigSchema(config, source);
|
|
||||||
this.validateRules(config.rules, source, getAdditionalRule);
|
|
||||||
this.validateEnvironment(config.env, source, getAdditionalEnv);
|
|
||||||
this.validateGlobals(config.globals, source);
|
|
||||||
|
|
||||||
for (const override of config.overrides || []) {
|
|
||||||
this.validateRules(override.rules, source, getAdditionalRule);
|
|
||||||
this.validateEnvironment(override.env, source, getAdditionalEnv);
|
|
||||||
this.validateGlobals(config.globals, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate config array object.
|
|
||||||
* @param {ConfigArray} configArray The config array to validate.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
validateConfigArray(configArray) {
|
|
||||||
const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);
|
|
||||||
const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);
|
|
||||||
const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);
|
|
||||||
|
|
||||||
// Validate.
|
|
||||||
for (const element of configArray) {
|
|
||||||
if (validated.has(element)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
validated.add(element);
|
|
||||||
|
|
||||||
this.validateEnvironment(element.env, element.name, getPluginEnv);
|
|
||||||
this.validateGlobals(element.globals, element.name);
|
|
||||||
this.validateProcessor(element.processor, element.name, getPluginProcessor);
|
|
||||||
this.validateRules(element.rules, element.name, getPluginRule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,64 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Provide the function that emits deprecation warnings.
|
|
||||||
* @author Toru Nagashima <http://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Requirements
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Private
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Defitions for deprecation warnings.
|
|
||||||
const deprecationWarningMessages = {
|
|
||||||
ESLINT_LEGACY_ECMAFEATURES:
|
|
||||||
"The 'ecmaFeatures' config file property is deprecated and has no effect.",
|
|
||||||
ESLINT_PERSONAL_CONFIG_LOAD:
|
|
||||||
"'~/.eslintrc.*' config files have been deprecated. " +
|
|
||||||
"Please use a config file per project or the '--config' option.",
|
|
||||||
ESLINT_PERSONAL_CONFIG_SUPPRESS:
|
|
||||||
"'~/.eslintrc.*' config files have been deprecated. " +
|
|
||||||
"Please remove it or add 'root:true' to the config files in your " +
|
|
||||||
"projects in order to avoid loading '~/.eslintrc.*' accidentally."
|
|
||||||
};
|
|
||||||
|
|
||||||
const sourceFileErrorCache = new Set();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
|
|
||||||
* for each unique file path, but repeated invocations with the same file path have no effect.
|
|
||||||
* No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
|
|
||||||
* @param {string} source The name of the configuration source to report the warning for.
|
|
||||||
* @param {string} errorCode The warning message to show.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function emitDeprecationWarning(source, errorCode) {
|
|
||||||
const cacheKey = JSON.stringify({ source, errorCode });
|
|
||||||
|
|
||||||
if (sourceFileErrorCache.has(cacheKey)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sourceFileErrorCache.add(cacheKey);
|
|
||||||
|
|
||||||
const rel = path.relative(process.cwd(), source);
|
|
||||||
const message = deprecationWarningMessages[errorCode];
|
|
||||||
|
|
||||||
process.emitWarning(
|
|
||||||
`${message} (found in "${rel}")`,
|
|
||||||
"DeprecationWarning",
|
|
||||||
errorCode
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
emitDeprecationWarning
|
|
||||||
};
|
|
|
@ -1,97 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Common helpers for naming of plugins, formatters and configs
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const NAMESPACE_REGEX = /^@.*\//iu;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Brings package name to correct format based on prefix
|
|
||||||
* @param {string} name The name of the package.
|
|
||||||
* @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
|
|
||||||
* @returns {string} Normalized name of the package
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function normalizePackageName(name, prefix) {
|
|
||||||
let normalizedName = name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On Windows, name can come in with Windows slashes instead of Unix slashes.
|
|
||||||
* Normalize to Unix first to avoid errors later on.
|
|
||||||
* https://github.com/eslint/eslint/issues/5644
|
|
||||||
*/
|
|
||||||
if (normalizedName.includes("\\")) {
|
|
||||||
normalizedName = normalizedName.replace(/\\/gu, "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalizedName.charAt(0) === "@") {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* it's a scoped package
|
|
||||||
* package name is the prefix, or just a username
|
|
||||||
*/
|
|
||||||
const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
|
|
||||||
scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
|
|
||||||
|
|
||||||
if (scopedPackageShortcutRegex.test(normalizedName)) {
|
|
||||||
normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
|
|
||||||
} else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* for scoped packages, insert the prefix after the first / unless
|
|
||||||
* the path is already @scope/eslint or @scope/eslint-xxx-yyy
|
|
||||||
*/
|
|
||||||
normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
|
|
||||||
}
|
|
||||||
} else if (!normalizedName.startsWith(`${prefix}-`)) {
|
|
||||||
normalizedName = `${prefix}-${normalizedName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return normalizedName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the prefix from a fullname.
|
|
||||||
* @param {string} fullname The term which may have the prefix.
|
|
||||||
* @param {string} prefix The prefix to remove.
|
|
||||||
* @returns {string} The term without prefix.
|
|
||||||
*/
|
|
||||||
function getShorthandName(fullname, prefix) {
|
|
||||||
if (fullname[0] === "@") {
|
|
||||||
let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
|
|
||||||
|
|
||||||
if (matchResult) {
|
|
||||||
return matchResult[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
|
|
||||||
if (matchResult) {
|
|
||||||
return `${matchResult[1]}/${matchResult[2]}`;
|
|
||||||
}
|
|
||||||
} else if (fullname.startsWith(`${prefix}-`)) {
|
|
||||||
return fullname.slice(prefix.length + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fullname;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the scope (namespace) of a term.
|
|
||||||
* @param {string} term The term which may have the namespace.
|
|
||||||
* @returns {string} The namespace of the term if it has one.
|
|
||||||
*/
|
|
||||||
function getNamespaceFromTerm(term) {
|
|
||||||
const match = term.match(NAMESPACE_REGEX);
|
|
||||||
|
|
||||||
return match ? match[0] : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
normalizePackageName,
|
|
||||||
getShorthandName,
|
|
||||||
getNamespaceFromTerm
|
|
||||||
};
|
|
|
@ -1,44 +0,0 @@
|
||||||
/**
|
|
||||||
* Utility for resolving a module relative to another module
|
|
||||||
* @author Teddy Katz
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const Module = require("module");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* `Module.createRequire` is added in v12.2.0. It supports URL as well.
|
|
||||||
* We only support the case where the argument is a filepath, not a URL.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins, node/no-deprecated-api
|
|
||||||
const createRequire = Module.createRequire || Module.createRequireFromPath;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves a Node module relative to another module
|
|
||||||
* @param {string} moduleName The name of a Node module, or a path to a Node module.
|
|
||||||
* @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be
|
|
||||||
* a file rather than a directory, but the file need not actually exist.
|
|
||||||
* @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`
|
|
||||||
*/
|
|
||||||
resolve(moduleName, relativeToPath) {
|
|
||||||
try {
|
|
||||||
return createRequire(relativeToPath).resolve(moduleName);
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
// This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.
|
|
||||||
if (
|
|
||||||
typeof error === "object" &&
|
|
||||||
error !== null &&
|
|
||||||
error.code === "MODULE_NOT_FOUND" &&
|
|
||||||
!error.requireStack &&
|
|
||||||
error.message.includes(moduleName)
|
|
||||||
) {
|
|
||||||
error.message += `\nRequire stack:\n- ${relativeToPath}`;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,150 +0,0 @@
|
||||||
/**
|
|
||||||
* @fileoverview Define common types for input completion.
|
|
||||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/** @type {any} */
|
|
||||||
module.exports = {};
|
|
||||||
|
|
||||||
/** @typedef {boolean | "off" | "readable" | "readonly" | "writable" | "writeable"} GlobalConf */
|
|
||||||
/** @typedef {0 | 1 | 2 | "off" | "warn" | "error"} SeverityConf */
|
|
||||||
/** @typedef {SeverityConf | [SeverityConf, ...any[]]} RuleConf */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} EcmaFeatures
|
|
||||||
* @property {boolean} [globalReturn] Enabling `return` statements at the top-level.
|
|
||||||
* @property {boolean} [jsx] Enabling JSX syntax.
|
|
||||||
* @property {boolean} [impliedStrict] Enabling strict mode always.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} ParserOptions
|
|
||||||
* @property {EcmaFeatures} [ecmaFeatures] The optional features.
|
|
||||||
* @property {3|5|6|7|8|9|10|11|12|2015|2016|2017|2018|2019|2020|2021} [ecmaVersion] The ECMAScript version (or revision number).
|
|
||||||
* @property {"script"|"module"} [sourceType] The source code type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} ConfigData
|
|
||||||
* @property {Record<string, boolean>} [env] The environment settings.
|
|
||||||
* @property {string | string[]} [extends] The path to other config files or the package name of shareable configs.
|
|
||||||
* @property {Record<string, GlobalConf>} [globals] The global variable settings.
|
|
||||||
* @property {string | string[]} [ignorePatterns] The glob patterns that ignore to lint.
|
|
||||||
* @property {boolean} [noInlineConfig] The flag that disables directive comments.
|
|
||||||
* @property {OverrideConfigData[]} [overrides] The override settings per kind of files.
|
|
||||||
* @property {string} [parser] The path to a parser or the package name of a parser.
|
|
||||||
* @property {ParserOptions} [parserOptions] The parser options.
|
|
||||||
* @property {string[]} [plugins] The plugin specifiers.
|
|
||||||
* @property {string} [processor] The processor specifier.
|
|
||||||
* @property {boolean} [reportUnusedDisableDirectives] The flag to report unused `eslint-disable` comments.
|
|
||||||
* @property {boolean} [root] The root flag.
|
|
||||||
* @property {Record<string, RuleConf>} [rules] The rule settings.
|
|
||||||
* @property {Object} [settings] The shared settings.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} OverrideConfigData
|
|
||||||
* @property {Record<string, boolean>} [env] The environment settings.
|
|
||||||
* @property {string | string[]} [excludedFiles] The glob pattarns for excluded files.
|
|
||||||
* @property {string | string[]} [extends] The path to other config files or the package name of shareable configs.
|
|
||||||
* @property {string | string[]} files The glob patterns for target files.
|
|
||||||
* @property {Record<string, GlobalConf>} [globals] The global variable settings.
|
|
||||||
* @property {boolean} [noInlineConfig] The flag that disables directive comments.
|
|
||||||
* @property {OverrideConfigData[]} [overrides] The override settings per kind of files.
|
|
||||||
* @property {string} [parser] The path to a parser or the package name of a parser.
|
|
||||||
* @property {ParserOptions} [parserOptions] The parser options.
|
|
||||||
* @property {string[]} [plugins] The plugin specifiers.
|
|
||||||
* @property {string} [processor] The processor specifier.
|
|
||||||
* @property {boolean} [reportUnusedDisableDirectives] The flag to report unused `eslint-disable` comments.
|
|
||||||
* @property {Record<string, RuleConf>} [rules] The rule settings.
|
|
||||||
* @property {Object} [settings] The shared settings.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} ParseResult
|
|
||||||
* @property {Object} ast The AST.
|
|
||||||
* @property {ScopeManager} [scopeManager] The scope manager of the AST.
|
|
||||||
* @property {Record<string, any>} [services] The services that the parser provides.
|
|
||||||
* @property {Record<string, string[]>} [visitorKeys] The visitor keys of the AST.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Parser
|
|
||||||
* @property {(text:string, options:ParserOptions) => Object} parse The definition of global variables.
|
|
||||||
* @property {(text:string, options:ParserOptions) => ParseResult} [parseForESLint] The parser options that will be enabled under this environment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Environment
|
|
||||||
* @property {Record<string, GlobalConf>} [globals] The definition of global variables.
|
|
||||||
* @property {ParserOptions} [parserOptions] The parser options that will be enabled under this environment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} LintMessage
|
|
||||||
* @property {number} column The 1-based column number.
|
|
||||||
* @property {number} [endColumn] The 1-based column number of the end location.
|
|
||||||
* @property {number} [endLine] The 1-based line number of the end location.
|
|
||||||
* @property {boolean} fatal If `true` then this is a fatal error.
|
|
||||||
* @property {{range:[number,number], text:string}} [fix] Information for autofix.
|
|
||||||
* @property {number} line The 1-based line number.
|
|
||||||
* @property {string} message The error message.
|
|
||||||
* @property {string|null} ruleId The ID of the rule which makes this message.
|
|
||||||
* @property {0|1|2} severity The severity of this message.
|
|
||||||
* @property {Array<{desc?: string, messageId?: string, fix: {range: [number, number], text: string}}>} [suggestions] Information for suggestions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} SuggestionResult
|
|
||||||
* @property {string} desc A short description.
|
|
||||||
* @property {string} [messageId] Id referencing a message for the description.
|
|
||||||
* @property {{ text: string, range: number[] }} fix fix result info
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Processor
|
|
||||||
* @property {(text:string, filename:string) => Array<string | { text:string, filename:string }>} [preprocess] The function to extract code blocks.
|
|
||||||
* @property {(messagesList:LintMessage[][], filename:string) => LintMessage[]} [postprocess] The function to merge messages.
|
|
||||||
* @property {boolean} [supportsAutofix] If `true` then it means the processor supports autofix.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} RuleMetaDocs
|
|
||||||
* @property {string} category The category of the rule.
|
|
||||||
* @property {string} description The description of the rule.
|
|
||||||
* @property {boolean} recommended If `true` then the rule is included in `eslint:recommended` preset.
|
|
||||||
* @property {string} url The URL of the rule documentation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} RuleMeta
|
|
||||||
* @property {boolean} [deprecated] If `true` then the rule has been deprecated.
|
|
||||||
* @property {RuleMetaDocs} docs The document information of the rule.
|
|
||||||
* @property {"code"|"whitespace"} [fixable] The autofix type.
|
|
||||||
* @property {Record<string,string>} [messages] The messages the rule reports.
|
|
||||||
* @property {string[]} [replacedBy] The IDs of the alternative rules.
|
|
||||||
* @property {Array|Object} schema The option schema of the rule.
|
|
||||||
* @property {"problem"|"suggestion"|"layout"} type The rule type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Rule
|
|
||||||
* @property {Function} create The factory of the rule.
|
|
||||||
* @property {RuleMeta} meta The meta data of the rule.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Plugin
|
|
||||||
* @property {Record<string, ConfigData>} [configs] The definition of plugin configs.
|
|
||||||
* @property {Record<string, Environment>} [environments] The definition of plugin environments.
|
|
||||||
* @property {Record<string, Processor>} [processors] The definition of plugin processors.
|
|
||||||
* @property {Record<string, Function | Rule>} [rules] The definition of plugin rules.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information of deprecated rules.
|
|
||||||
* @typedef {Object} DeprecatedRuleInfo
|
|
||||||
* @property {string} ruleId The rule ID.
|
|
||||||
* @property {string[]} replacedBy The rule IDs that replace this deprecated rule.
|
|
||||||
*/
|
|
|
@ -1,63 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@eslint/eslintrc",
|
|
||||||
"version": "0.4.3",
|
|
||||||
"description": "The legacy ESLintRC config file format for ESLint",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"files": [
|
|
||||||
"lib",
|
|
||||||
"conf",
|
|
||||||
"LICENSE"
|
|
||||||
],
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"lint": "eslint . --report-unused-disable-directives",
|
|
||||||
"fix": "npm run lint -- --fix",
|
|
||||||
"test": "mocha -R progress -c 'tests/lib/**/*.js'",
|
|
||||||
"generate-release": "eslint-generate-release",
|
|
||||||
"generate-alpharelease": "eslint-generate-prerelease alpha",
|
|
||||||
"generate-betarelease": "eslint-generate-prerelease beta",
|
|
||||||
"generate-rcrelease": "eslint-generate-prerelease rc",
|
|
||||||
"publish-release": "eslint-publish-release"
|
|
||||||
},
|
|
||||||
"repository": "eslint/eslintrc",
|
|
||||||
"keywords": [
|
|
||||||
"ESLint",
|
|
||||||
"ESLintRC",
|
|
||||||
"Configuration"
|
|
||||||
],
|
|
||||||
"author": "Nicholas C. Zakas",
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/eslint/eslintrc/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/eslint/eslintrc#readme",
|
|
||||||
"devDependencies": {
|
|
||||||
"chai": "^4.2.0",
|
|
||||||
"eslint": "^7.21.0",
|
|
||||||
"eslint-config-eslint": "^7.0.0",
|
|
||||||
"eslint-plugin-jsdoc": "^32.2.0",
|
|
||||||
"eslint-plugin-node": "^11.1.0",
|
|
||||||
"eslint-release": "^3.1.2",
|
|
||||||
"fs-teardown": "0.1.1",
|
|
||||||
"mocha": "^8.1.1",
|
|
||||||
"shelljs": "^0.8.4",
|
|
||||||
"sinon": "^9.2.0",
|
|
||||||
"temp-dir": "^2.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ajv": "^6.12.4",
|
|
||||||
"debug": "^4.1.1",
|
|
||||||
"espree": "^7.3.0",
|
|
||||||
"globals": "^13.9.0",
|
|
||||||
"ignore": "^4.0.6",
|
|
||||||
"import-fresh": "^3.2.1",
|
|
||||||
"js-yaml": "^3.13.1",
|
|
||||||
"minimatch": "^3.0.4",
|
|
||||||
"strip-json-comments": "^3.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^10.12.0 || >=12.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,201 +0,0 @@
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
|
@ -1,258 +0,0 @@
|
||||||
# Config Array
|
|
||||||
|
|
||||||
by [Nicholas C. Zakas](https://humanwhocodes.com)
|
|
||||||
|
|
||||||
If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate).
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
A config array is a way of managing configurations that are based on glob pattern matching of filenames. Each config array contains the information needed to determine the correct configuration for any file based on the filename.
|
|
||||||
|
|
||||||
## Background
|
|
||||||
|
|
||||||
In 2019, I submitted an [ESLint RFC](https://github.com/eslint/rfcs/pull/9) proposing a new way of configuring ESLint. The goal was to streamline what had become an increasingly complicated configuration process. Over several iterations, this proposal was eventually born.
|
|
||||||
|
|
||||||
The basic idea is that all configuration, including overrides, can be represented by a single array where each item in the array is a config object. Config objects appearing later in the array override config objects appearing earlier in the array. You can calculate a config for a given file by traversing all config objects in the array to find the ones that match the filename. Matching is done by specifying glob patterns in `files` and `ignores` properties on each config object. Here's an example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
export default [
|
|
||||||
|
|
||||||
// match all JSON files
|
|
||||||
{
|
|
||||||
name: "JSON Handler",
|
|
||||||
files: ["**/*.json"],
|
|
||||||
handler: jsonHandler
|
|
||||||
},
|
|
||||||
|
|
||||||
// match only package.json
|
|
||||||
{
|
|
||||||
name: "package.json Handler",
|
|
||||||
files: ["package.json"],
|
|
||||||
handler: packageJsonHandler
|
|
||||||
}
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, there are two config objects: the first matches all JSON files in all directories and the second matches just `package.json` in the base path directory (all the globs are evaluated as relative to a base path that can be specified). When you retrieve a configuration for `foo.json`, only the first config object matches so `handler` is equal to `jsonHandler`; when you retrieve a configuration for `package.json`, `handler` is equal to `packageJsonHandler` (because both config objects match, the second one wins).
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
You can install the package using npm or Yarn:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install @humanwhocodes/config-array --save
|
|
||||||
|
|
||||||
# or
|
|
||||||
|
|
||||||
yarn add @humanwhocodes/config-array
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
First, import the `ConfigArray` constructor:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { ConfigArray } from "@humanwhocodes/config-array";
|
|
||||||
|
|
||||||
// or using CommonJS
|
|
||||||
|
|
||||||
const { ConfigArray } = require("@humanwhocodes/config-array");
|
|
||||||
```
|
|
||||||
|
|
||||||
When you create a new instance of `ConfigArray`, you must pass in two arguments: an array of configs and an options object. The array of configs is most likely read in from a configuration file, so here's a typical example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const configFilename = path.resolve(process.cwd(), "my.config.js");
|
|
||||||
const { default: rawConfigs } = await import(configFilename);
|
|
||||||
const configs = new ConfigArray(rawConfigs, {
|
|
||||||
|
|
||||||
// the path to match filenames from
|
|
||||||
basePath: process.cwd(),
|
|
||||||
|
|
||||||
// additional items in each config
|
|
||||||
schema: mySchema
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
This example reads in an object or array from `my.config.js` and passes it into the `ConfigArray` constructor as the first argument. The second argument is an object specifying the `basePath` (the directoy in which `my.config.js` is found) and a `schema` to define the additional properties of a config object beyond `files`, `ignores`, and `name`.
|
|
||||||
|
|
||||||
### Specifying a Schema
|
|
||||||
|
|
||||||
The `schema` option is required for you to use additional properties in config objects. The schema is object that follows the format of an [`ObjectSchema`](https://npmjs.com/package/@humanwhocodes/object-schema). The schema specifies both validation and merge rules that the `ConfigArray` instance needs to combine configs when there are multiple matches. Here's an example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const configFilename = path.resolve(process.cwd(), "my.config.js");
|
|
||||||
const { default: rawConfigs } = await import(configFilename);
|
|
||||||
|
|
||||||
const mySchema = {
|
|
||||||
|
|
||||||
// define the handler key in configs
|
|
||||||
handler: {
|
|
||||||
required: true,
|
|
||||||
merge(a, b) {
|
|
||||||
if (!b) return a;
|
|
||||||
if (!a) return b;
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
if (typeof value !== "function") {
|
|
||||||
throw new TypeError("Function expected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const configs = new ConfigArray(rawConfigs, {
|
|
||||||
|
|
||||||
// the path to match filenames from
|
|
||||||
basePath: process.cwd(),
|
|
||||||
|
|
||||||
// additional items in each config
|
|
||||||
schema: mySchema
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Config Arrays
|
|
||||||
|
|
||||||
Config arrays can be multidimensional, so it's possible for a config array to contain another config array, such as:
|
|
||||||
|
|
||||||
```js
|
|
||||||
export default [
|
|
||||||
|
|
||||||
// JS config
|
|
||||||
{
|
|
||||||
files: ["**/*.js"],
|
|
||||||
handler: jsHandler
|
|
||||||
},
|
|
||||||
|
|
||||||
// JSON configs
|
|
||||||
[
|
|
||||||
|
|
||||||
// match all JSON files
|
|
||||||
{
|
|
||||||
name: "JSON Handler",
|
|
||||||
files: ["**/*.json"],
|
|
||||||
handler: jsonHandler
|
|
||||||
},
|
|
||||||
|
|
||||||
// match only package.json
|
|
||||||
{
|
|
||||||
name: "package.json Handler",
|
|
||||||
files: ["package.json"],
|
|
||||||
handler: packageJsonHandler
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// filename must match function
|
|
||||||
{
|
|
||||||
files: [ filePath => filePath.endsWith(".md") ],
|
|
||||||
handler: markdownHandler
|
|
||||||
},
|
|
||||||
|
|
||||||
// filename must match all patterns in subarray
|
|
||||||
{
|
|
||||||
files: [ ["*.test.*", "*.js"] ],
|
|
||||||
handler: jsTestHandler
|
|
||||||
},
|
|
||||||
|
|
||||||
// filename must not match patterns beginning with !
|
|
||||||
{
|
|
||||||
name: "Non-JS files",
|
|
||||||
files: ["!*.js"],
|
|
||||||
settings: {
|
|
||||||
js: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, the array contains both config objects and a config array. When a config array is normalized (see details below), it is flattened so only config objects remain. However, the order of evaluation remains the same.
|
|
||||||
|
|
||||||
If the `files` array contains a function, then that function is called with the absolute path of the file and is expected to return `true` if there is a match and `false` if not. (The `ignores` array can also contain functions.)
|
|
||||||
|
|
||||||
If the `files` array contains an item that is an array of strings and functions, then all patterns must match in order for the config to match. In the preceding examples, both `*.test.*` and `*.js` must match in order for the config object to be used.
|
|
||||||
|
|
||||||
If a pattern in the files array begins with `!` then it excludes that pattern. In the preceding example, any filename that doesn't end with `.js` will automatically getting a `settings.js` property set to `false`.
|
|
||||||
|
|
||||||
### Config Functions
|
|
||||||
|
|
||||||
Config arrays can also include config functions. A config function accepts a single parameter, `context` (defined by you), and must return either a config object or a config array (it cannot return another function). Config functions allow end users to execute code in the creation of appropriate config objects. Here's an example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
export default [
|
|
||||||
|
|
||||||
// JS config
|
|
||||||
{
|
|
||||||
files: ["**/*.js"],
|
|
||||||
handler: jsHandler
|
|
||||||
},
|
|
||||||
|
|
||||||
// JSON configs
|
|
||||||
function (context) {
|
|
||||||
return [
|
|
||||||
|
|
||||||
// match all JSON files
|
|
||||||
{
|
|
||||||
name: context.name + " JSON Handler",
|
|
||||||
files: ["**/*.json"],
|
|
||||||
handler: jsonHandler
|
|
||||||
},
|
|
||||||
|
|
||||||
// match only package.json
|
|
||||||
{
|
|
||||||
name: context.name + " package.json Handler",
|
|
||||||
files: ["package.json"],
|
|
||||||
handler: packageJsonHandler
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
When a config array is normalized, each function is executed and replaced in the config array with the return value.
|
|
||||||
|
|
||||||
**Note:** Config functions cannot be async. This will be added in a future version.
|
|
||||||
|
|
||||||
### Normalizing Config Arrays
|
|
||||||
|
|
||||||
Once a config array has been created and loaded with all of the raw config data, it must be normalized before it can be used. The normalization process goes through and flattens the config array as well as executing all config functions to get their final values.
|
|
||||||
|
|
||||||
To normalize a config array, call the `normalize()` method and pass in a context object:
|
|
||||||
|
|
||||||
```js
|
|
||||||
await configs.normalize({
|
|
||||||
name: "MyApp"
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
The `normalize()` method returns a promise, so be sure to use the `await` operator. The config array instance is normalized in-place, so you don't need to create a new variable.
|
|
||||||
|
|
||||||
**Important:** Once a `ConfigArray` is normalized, it cannot be changed further. You can, however, create a new `ConfigArray` and pass in the normalized instance to create an unnormalized copy.
|
|
||||||
|
|
||||||
### Getting Config for a File
|
|
||||||
|
|
||||||
To get the config for a file, use the `getConfig()` method on a normalized config array and pass in the filename to get a config for:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// pass in absolute filename
|
|
||||||
const fileConfig = configs.getConfig(path.resolve(process.cwd(), "package.json"));
|
|
||||||
```
|
|
||||||
|
|
||||||
The config array always returns an object, even if there are no configs matching the given filename. You can then inspect the returned config object to determine how to proceed.
|
|
||||||
|
|
||||||
A few things to keep in mind:
|
|
||||||
|
|
||||||
* You must pass in the absolute filename to get a config for.
|
|
||||||
* The returned config object never has `files`, `ignores`, or `name` properties; the only properties on the object will be the other configuration options specified.
|
|
||||||
* The config array caches configs, so subsequent calls to `getConfig()` with the same filename will return in a fast lookup rather than another calculation.
|
|
||||||
|
|
||||||
## Acknowledgements
|
|
||||||
|
|
||||||
The design of this project was influenced by feedback on the ESLint RFC, and incorporates ideas from:
|
|
||||||
|
|
||||||
* Teddy Katz (@not-an-aardvark)
|
|
||||||
* Toru Nagashima (@mysticatea)
|
|
||||||
* Kai Cataldo (@kaicataldo)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Apache 2.0
|
|
|
@ -1,457 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
Object.defineProperty(exports, '__esModule', { value: true });
|
|
||||||
|
|
||||||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
|
||||||
|
|
||||||
var path = _interopDefault(require('path'));
|
|
||||||
var minimatch = _interopDefault(require('minimatch'));
|
|
||||||
var createDebug = _interopDefault(require('debug'));
|
|
||||||
var objectSchema = require('@humanwhocodes/object-schema');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @fileoverview ConfigSchema
|
|
||||||
* @author Nicholas C. Zakas
|
|
||||||
*/
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assets that a given value is an array.
|
|
||||||
* @param {*} value The value to check.
|
|
||||||
* @returns {void}
|
|
||||||
* @throws {TypeError} When the value is not an array.
|
|
||||||
*/
|
|
||||||
function assertIsArray(value) {
|
|
||||||
if (!Array.isArray(value)) {
|
|
||||||
throw new TypeError('Expected value to be an array.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assets that a given value is an array containing only strings and functions.
|
|
||||||
* @param {*} value The value to check.
|
|
||||||
* @returns {void}
|
|
||||||
* @throws {TypeError} When the value is not an array of strings and functions.
|
|
||||||
*/
|
|
||||||
function assertIsArrayOfStringsAndFunctions(value, name) {
|
|
||||||
assertIsArray(value);
|
|
||||||
|
|
||||||
if (value.some(item => typeof item !== 'string' && typeof item !== 'function')) {
|
|
||||||
throw new TypeError('Expected array to only contain strings.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Exports
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base schema that every ConfigArray uses.
|
|
||||||
* @type Object
|
|
||||||
*/
|
|
||||||
const baseSchema = Object.freeze({
|
|
||||||
name: {
|
|
||||||
required: false,
|
|
||||||
merge() {
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
if (typeof value !== 'string') {
|
|
||||||
throw new TypeError('Property must be a string.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
required: false,
|
|
||||||
merge() {
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
|
|
||||||
// first check if it's an array
|
|
||||||
assertIsArray(value);
|
|
||||||
|
|
||||||
// then check each member
|
|
||||||
value.forEach(item => {
|
|
||||||
if (Array.isArray(item)) {
|
|
||||||
assertIsArrayOfStringsAndFunctions(item);
|
|
||||||
} else if (typeof item !== 'string' && typeof item !== 'function') {
|
|
||||||
throw new TypeError('Items must be a string, a function, or an array of strings and functions.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ignores: {
|
|
||||||
required: false,
|
|
||||||
merge() {
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
validate: assertIsArrayOfStringsAndFunctions
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @fileoverview ConfigArray
|
|
||||||
* @author Nicholas C. Zakas
|
|
||||||
*/
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Helpers
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const debug = createDebug('@hwc/config-array');
|
|
||||||
|
|
||||||
const MINIMATCH_OPTIONS = {
|
|
||||||
matchBase: true
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shorthand for checking if a value is a string.
|
|
||||||
* @param {any} value The value to check.
|
|
||||||
* @returns {boolean} True if a string, false if not.
|
|
||||||
*/
|
|
||||||
function isString(value) {
|
|
||||||
return typeof value === 'string';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalizes a `ConfigArray` by flattening it and executing any functions
|
|
||||||
* that are found inside.
|
|
||||||
* @param {Array} items The items in a `ConfigArray`.
|
|
||||||
* @param {Object} context The context object to pass into any function
|
|
||||||
* found.
|
|
||||||
* @returns {Array} A flattened array containing only config objects.
|
|
||||||
* @throws {TypeError} When a config function returns a function.
|
|
||||||
*/
|
|
||||||
async function normalize(items, context) {
|
|
||||||
|
|
||||||
// TODO: Allow async config functions
|
|
||||||
|
|
||||||
function *flatTraverse(array) {
|
|
||||||
for (let item of array) {
|
|
||||||
if (typeof item === 'function') {
|
|
||||||
item = item(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(item)) {
|
|
||||||
yield * flatTraverse(item);
|
|
||||||
} else if (typeof item === 'function') {
|
|
||||||
throw new TypeError('A config function can only return an object or array.');
|
|
||||||
} else {
|
|
||||||
yield item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...flatTraverse(items)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if a given file path is matched by a config. If the config
|
|
||||||
* has no `files` field, then it matches; otherwise, if a `files` field
|
|
||||||
* is present then we match the globs in `files` and exclude any globs in
|
|
||||||
* `ignores`.
|
|
||||||
* @param {string} filePath The absolute file path to check.
|
|
||||||
* @param {Object} config The config object to check.
|
|
||||||
* @returns {boolean} True if the file path is matched by the config,
|
|
||||||
* false if not.
|
|
||||||
*/
|
|
||||||
function pathMatches(filePath, basePath, config) {
|
|
||||||
|
|
||||||
// a config without a `files` field always matches
|
|
||||||
if (!config.files) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if files isn't an array, throw an error
|
|
||||||
if (!Array.isArray(config.files) || config.files.length === 0) {
|
|
||||||
throw new TypeError('The files key must be a non-empty array.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const relativeFilePath = path.relative(basePath, filePath);
|
|
||||||
|
|
||||||
// match both strings and functions
|
|
||||||
const match = pattern => {
|
|
||||||
if (isString(pattern)) {
|
|
||||||
return minimatch(relativeFilePath, pattern, MINIMATCH_OPTIONS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof pattern === 'function') {
|
|
||||||
return pattern(filePath);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// check for all matches to config.files
|
|
||||||
let matches = config.files.some(pattern => {
|
|
||||||
if (Array.isArray(pattern)) {
|
|
||||||
return pattern.every(match);
|
|
||||||
}
|
|
||||||
|
|
||||||
return match(pattern);
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the file path matches the config.files patterns, then check to see
|
|
||||||
* if there are any files to ignore.
|
|
||||||
*/
|
|
||||||
if (matches && config.ignores) {
|
|
||||||
matches = !config.ignores.some(pattern => {
|
|
||||||
return minimatch(filePath, pattern, MINIMATCH_OPTIONS);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that a ConfigArray has been normalized.
|
|
||||||
* @param {ConfigArray} configArray The ConfigArray to check.
|
|
||||||
* @returns {void}
|
|
||||||
* @throws {Error} When the `ConfigArray` is not normalized.
|
|
||||||
*/
|
|
||||||
function assertNormalized(configArray) {
|
|
||||||
// TODO: Throw more verbose error
|
|
||||||
if (!configArray.isNormalized()) {
|
|
||||||
throw new Error('ConfigArray must be normalized to perform this operation.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Public Interface
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const ConfigArraySymbol = {
|
|
||||||
isNormalized: Symbol('isNormalized'),
|
|
||||||
configCache: Symbol('configCache'),
|
|
||||||
schema: Symbol('schema'),
|
|
||||||
finalizeConfig: Symbol('finalizeConfig'),
|
|
||||||
preprocessConfig: Symbol('preprocessConfig')
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an array of config objects and provides method for working with
|
|
||||||
* those config objects.
|
|
||||||
*/
|
|
||||||
class ConfigArray extends Array {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of ConfigArray.
|
|
||||||
* @param {Iterable|Function|Object} configs An iterable yielding config
|
|
||||||
* objects, or a config function, or a config object.
|
|
||||||
* @param {string} [options.basePath=""] The path of the config file
|
|
||||||
* @param {boolean} [options.normalized=false] Flag indicating if the
|
|
||||||
* configs have already been normalized.
|
|
||||||
* @param {Object} [options.schema] The additional schema
|
|
||||||
* definitions to use for the ConfigArray schema.
|
|
||||||
*/
|
|
||||||
constructor(configs, { basePath = '', normalized = false, schema: customSchema } = {}) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks if the array has been normalized.
|
|
||||||
* @property isNormalized
|
|
||||||
* @type boolean
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this[ConfigArraySymbol.isNormalized] = normalized;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The schema used for validating and merging configs.
|
|
||||||
* @property schema
|
|
||||||
* @type ObjectSchema
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this[ConfigArraySymbol.schema] = new objectSchema.ObjectSchema({
|
|
||||||
...customSchema,
|
|
||||||
...baseSchema
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path of the config file that this array was loaded from.
|
|
||||||
* This is used to calculate filename matches.
|
|
||||||
* @property basePath
|
|
||||||
* @type string
|
|
||||||
*/
|
|
||||||
this.basePath = basePath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A cache to store calculated configs for faster repeat lookup.
|
|
||||||
* @property configCache
|
|
||||||
* @type Map
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this[ConfigArraySymbol.configCache] = new Map();
|
|
||||||
|
|
||||||
// load the configs into this array
|
|
||||||
if (Array.isArray(configs)) {
|
|
||||||
this.push(...configs);
|
|
||||||
} else {
|
|
||||||
this.push(configs);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevent normal array methods from creating a new `ConfigArray` instance.
|
|
||||||
* This is to ensure that methods such as `slice()` won't try to create a
|
|
||||||
* new instance of `ConfigArray` behind the scenes as doing so may throw
|
|
||||||
* an error due to the different constructor signature.
|
|
||||||
* @returns {Function} The `Array` constructor.
|
|
||||||
*/
|
|
||||||
static get [Symbol.species]() {
|
|
||||||
return Array;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the `files` globs from every config object in the array.
|
|
||||||
* Negated patterns (those beginning with `!`) are not returned.
|
|
||||||
* This can be used to determine which files will be matched by a
|
|
||||||
* config array or to use as a glob pattern when no patterns are provided
|
|
||||||
* for a command line interface.
|
|
||||||
* @returns {string[]} An array of string patterns.
|
|
||||||
*/
|
|
||||||
get files() {
|
|
||||||
|
|
||||||
assertNormalized(this);
|
|
||||||
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
for (const config of this) {
|
|
||||||
if (config.files) {
|
|
||||||
config.files.forEach(filePattern => {
|
|
||||||
if (Array.isArray(filePattern)) {
|
|
||||||
result.push(...filePattern.filter(pattern => {
|
|
||||||
return isString(pattern) && !pattern.startsWith('!');
|
|
||||||
}));
|
|
||||||
} else if (isString(filePattern) && !filePattern.startsWith('!')) {
|
|
||||||
result.push(filePattern);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the file globs that should always be ignored regardless of
|
|
||||||
* the matching `files` fields in any configs. This is necessary to mimic
|
|
||||||
* the behavior of things like .gitignore and .eslintignore, allowing a
|
|
||||||
* globbing operation to be faster.
|
|
||||||
* @returns {string[]} An array of string patterns to be ignored.
|
|
||||||
*/
|
|
||||||
get ignores() {
|
|
||||||
|
|
||||||
assertNormalized(this);
|
|
||||||
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
for (const config of this) {
|
|
||||||
if (config.ignores && !config.files) {
|
|
||||||
result.push(...config.ignores.filter(isString));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates if the config array has been normalized.
|
|
||||||
* @returns {boolean} True if the config array is normalized, false if not.
|
|
||||||
*/
|
|
||||||
isNormalized() {
|
|
||||||
return this[ConfigArraySymbol.isNormalized];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalizes a config array by flattening embedded arrays and executing
|
|
||||||
* config functions.
|
|
||||||
* @param {ConfigContext} context The context object for config functions.
|
|
||||||
* @returns {ConfigArray} A new ConfigArray instance that is normalized.
|
|
||||||
*/
|
|
||||||
async normalize(context = {}) {
|
|
||||||
|
|
||||||
if (!this.isNormalized()) {
|
|
||||||
const normalizedConfigs = await normalize(this, context);
|
|
||||||
this.length = 0;
|
|
||||||
this.push(...normalizedConfigs.map(this[ConfigArraySymbol.preprocessConfig]));
|
|
||||||
this[ConfigArraySymbol.isNormalized] = true;
|
|
||||||
|
|
||||||
// prevent further changes
|
|
||||||
Object.freeze(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalizes the state of a config before being cached and returned by
|
|
||||||
* `getConfig()`. Does nothing by default but is provided to be
|
|
||||||
* overridden by subclasses as necessary.
|
|
||||||
* @param {Object} config The config to finalize.
|
|
||||||
* @returns {Object} The finalized config.
|
|
||||||
*/
|
|
||||||
[ConfigArraySymbol.finalizeConfig](config) {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preprocesses a config during the normalization process. This is the
|
|
||||||
* method to override if you want to convert an array item before it is
|
|
||||||
* validated for the first time. For example, if you want to replace a
|
|
||||||
* string with an object, this is the method to override.
|
|
||||||
* @param {Object} config The config to preprocess.
|
|
||||||
* @returns {Object} The config to use in place of the argument.
|
|
||||||
*/
|
|
||||||
[ConfigArraySymbol.preprocessConfig](config) {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the config object for a given file path.
|
|
||||||
* @param {string} filePath The complete path of a file to get a config for.
|
|
||||||
* @returns {Object} The config object for this file.
|
|
||||||
*/
|
|
||||||
getConfig(filePath) {
|
|
||||||
|
|
||||||
assertNormalized(this);
|
|
||||||
|
|
||||||
// first check the cache to avoid duplicate work
|
|
||||||
let finalConfig = this[ConfigArraySymbol.configCache].get(filePath);
|
|
||||||
|
|
||||||
if (finalConfig) {
|
|
||||||
return finalConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No config found in cache, so calculate a new one
|
|
||||||
|
|
||||||
const matchingConfigs = [];
|
|
||||||
|
|
||||||
for (const config of this) {
|
|
||||||
if (pathMatches(filePath, this.basePath, config)) {
|
|
||||||
debug(`Matching config found for ${filePath}`);
|
|
||||||
matchingConfigs.push(config);
|
|
||||||
} else {
|
|
||||||
debug(`No matching config found for ${filePath}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finalConfig = matchingConfigs.reduce((result, config) => {
|
|
||||||
return this[ConfigArraySymbol.schema].merge(result, config);
|
|
||||||
}, {}, this);
|
|
||||||
|
|
||||||
finalConfig = this[ConfigArraySymbol.finalizeConfig](finalConfig);
|
|
||||||
|
|
||||||
this[ConfigArraySymbol.configCache].set(filePath, finalConfig);
|
|
||||||
|
|
||||||
return finalConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.ConfigArray = ConfigArray;
|
|
||||||
exports.ConfigArraySymbol = ConfigArraySymbol;
|
|
|
@ -1,61 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@humanwhocodes/config-array",
|
|
||||||
"version": "0.5.0",
|
|
||||||
"description": "Glob-based configuration matching.",
|
|
||||||
"author": "Nicholas C. Zakas",
|
|
||||||
"main": "api.js",
|
|
||||||
"files": [
|
|
||||||
"api.js"
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/humanwhocodes/config-array.git"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/humanwhocodes/config-array/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/humanwhocodes/config-array#readme",
|
|
||||||
"scripts": {
|
|
||||||
"build": "rollup -c",
|
|
||||||
"format": "nitpik",
|
|
||||||
"lint": "eslint *.config.js src/*.js tests/*.js",
|
|
||||||
"prepublish": "npm run build",
|
|
||||||
"test:coverage": "nyc --include src/*.js npm run test",
|
|
||||||
"test": "mocha -r esm tests/ --recursive"
|
|
||||||
},
|
|
||||||
"gitHooks": {
|
|
||||||
"pre-commit": "lint-staged"
|
|
||||||
},
|
|
||||||
"lint-staged": {
|
|
||||||
"*.js": [
|
|
||||||
"nitpik",
|
|
||||||
"eslint --fix --ignore-pattern '!.eslintrc.js'"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"configuration",
|
|
||||||
"configarray",
|
|
||||||
"config file"
|
|
||||||
],
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.10.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@humanwhocodes/object-schema": "^1.2.0",
|
|
||||||
"debug": "^4.1.1",
|
|
||||||
"minimatch": "^3.0.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@nitpik/javascript": "^0.3.3",
|
|
||||||
"@nitpik/node": "0.0.5",
|
|
||||||
"chai": "^4.2.0",
|
|
||||||
"eslint": "^6.7.1",
|
|
||||||
"esm": "^3.2.25",
|
|
||||||
"lint-staged": "^10.2.8",
|
|
||||||
"mocha": "^6.1.4",
|
|
||||||
"nyc": "^14.1.1",
|
|
||||||
"rollup": "^1.12.3",
|
|
||||||
"yorkie": "^2.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
"env": {
|
|
||||||
"commonjs": true,
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2018
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"indent": [
|
|
||||||
"error",
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"linebreak-style": [
|
|
||||||
"error",
|
|
||||||
"unix"
|
|
||||||
],
|
|
||||||
"quotes": [
|
|
||||||
"error",
|
|
||||||
"double"
|
|
||||||
],
|
|
||||||
"semi": [
|
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,14 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "8"
|
|
||||||
- "9"
|
|
||||||
- "10"
|
|
||||||
- "11"
|
|
||||||
sudo: false
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
# Run npm test always
|
|
||||||
script:
|
|
||||||
- "npm test"
|
|
|
@ -1,29 +0,0 @@
|
||||||
BSD 3-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2019, Human Who Codes
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the copyright holder nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
@ -1,234 +0,0 @@
|
||||||
# JavaScript ObjectSchema Package
|
|
||||||
|
|
||||||
by [Nicholas C. Zakas](https://humanwhocodes.com)
|
|
||||||
|
|
||||||
If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate).
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
A JavaScript object merge/validation utility where you can define a different merge and validation strategy for each key. This is helpful when you need to validate complex data structures and then merge them in a way that is more complex than `Object.assign()`.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
You can install using either npm:
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install @humanwhocodes/object-schema
|
|
||||||
```
|
|
||||||
|
|
||||||
Or Yarn:
|
|
||||||
|
|
||||||
```
|
|
||||||
yarn add @humanwhocodes/object-schema
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Use CommonJS to get access to the `ObjectSchema` constructor:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const { ObjectSchema } = require("@humanwhocodes/object-schema");
|
|
||||||
|
|
||||||
const schema = new ObjectSchema({
|
|
||||||
|
|
||||||
// define a definition for the "downloads" key
|
|
||||||
downloads: {
|
|
||||||
required: true,
|
|
||||||
merge(value1, value2) {
|
|
||||||
return value1 + value2;
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
if (typeof value !== "number") {
|
|
||||||
throw new Error("Expected downloads to be a number.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// define a strategy for the "versions" key
|
|
||||||
version: {
|
|
||||||
required: true,
|
|
||||||
merge(value1, value2) {
|
|
||||||
return value1.concat(value2);
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
if (!Array.isArray(value)) {
|
|
||||||
throw new Error("Expected versions to be an array.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const record1 = {
|
|
||||||
downloads: 25,
|
|
||||||
versions: [
|
|
||||||
"v1.0.0",
|
|
||||||
"v1.1.0",
|
|
||||||
"v1.2.0"
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
const record2 = {
|
|
||||||
downloads: 125,
|
|
||||||
versions: [
|
|
||||||
"v2.0.0",
|
|
||||||
"v2.1.0",
|
|
||||||
"v3.0.0"
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
// make sure the records are valid
|
|
||||||
schema.validate(record1);
|
|
||||||
schema.validate(record2);
|
|
||||||
|
|
||||||
// merge together (schema.merge() accepts any number of objects)
|
|
||||||
const result = schema.merge(record1, record2);
|
|
||||||
|
|
||||||
// result looks like this:
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
downloads: 75,
|
|
||||||
versions: [
|
|
||||||
"v1.0.0",
|
|
||||||
"v1.1.0",
|
|
||||||
"v1.2.0",
|
|
||||||
"v2.0.0",
|
|
||||||
"v2.1.0",
|
|
||||||
"v3.0.0"
|
|
||||||
]
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tips and Tricks
|
|
||||||
|
|
||||||
### Named merge strategies
|
|
||||||
|
|
||||||
Instead of specifying a `merge()` method, you can specify one of the following strings to use a default merge strategy:
|
|
||||||
|
|
||||||
* `"assign"` - use `Object.assign()` to merge the two values into one object.
|
|
||||||
* `"overwrite"` - the second value always replaces the first.
|
|
||||||
* `"replace"` - the second value replaces the first if the second is not `undefined`.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const schema = new ObjectSchema({
|
|
||||||
name: {
|
|
||||||
merge: "replace",
|
|
||||||
validate() {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Named validation strategies
|
|
||||||
|
|
||||||
Instead of specifying a `validate()` method, you can specify one of the following strings to use a default validation strategy:
|
|
||||||
|
|
||||||
* `"array"` - value must be an array.
|
|
||||||
* `"boolean"` - value must be a boolean.
|
|
||||||
* `"number"` - value must be a number.
|
|
||||||
* `"object"` - value must be an object.
|
|
||||||
* `"object?"` - value must be an object or null.
|
|
||||||
* `"string"` - value must be a string.
|
|
||||||
* `"string!"` - value must be a non-empty string.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const schema = new ObjectSchema({
|
|
||||||
name: {
|
|
||||||
merge: "replace",
|
|
||||||
validate: "string"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Subschemas
|
|
||||||
|
|
||||||
If you are defining a key that is, itself, an object, you can simplify the process by using a subschema. Instead of defining `merge()` and `validate()`, assign a `schema` key that contains a schema definition, like this:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const schema = new ObjectSchema({
|
|
||||||
name: {
|
|
||||||
schema: {
|
|
||||||
first: {
|
|
||||||
merge: "replace",
|
|
||||||
validate: "string"
|
|
||||||
},
|
|
||||||
last: {
|
|
||||||
merge: "replace",
|
|
||||||
validate: "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
schema.validate({
|
|
||||||
name: {
|
|
||||||
first: "n",
|
|
||||||
last: "z"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Remove Keys During Merge
|
|
||||||
|
|
||||||
If the merge strategy for a key returns `undefined`, then the key will not appear in the final object. For example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const schema = new ObjectSchema({
|
|
||||||
date: {
|
|
||||||
merge() {
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
Date.parse(value); // throws an error when invalid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const object1 = { date: "5/5/2005" };
|
|
||||||
const object2 = { date: "6/6/2006" };
|
|
||||||
|
|
||||||
const result = schema.merge(object1, object2);
|
|
||||||
|
|
||||||
console.log("date" in result); // false
|
|
||||||
```
|
|
||||||
|
|
||||||
### Requiring Another Key Be Present
|
|
||||||
|
|
||||||
If you'd like the presence of one key to require the presence of another key, you can use the `requires` property to specify an array of other properties that any key requires. For example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const schema = new ObjectSchema();
|
|
||||||
|
|
||||||
const schema = new ObjectSchema({
|
|
||||||
date: {
|
|
||||||
merge() {
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
Date.parse(value); // throws an error when invalid
|
|
||||||
}
|
|
||||||
},
|
|
||||||
time: {
|
|
||||||
requires: ["date"],
|
|
||||||
merge(first, second) {
|
|
||||||
return second;
|
|
||||||
},
|
|
||||||
validate(value) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// throws error: Key "time" requires keys "date"
|
|
||||||
schema.validate({
|
|
||||||
time: "13:45"
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, even though `date` is an optional key, it is required to be present whenever `time` is present.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
BSD 3-Clause
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue