tools: update eslint

This updates eslint from v6.0.0-alpha.2 to v6.0.1

This also removes eslint-disable comments about `bigint` typeof
checks. Those would otherwise have caused linting errors now that
`bigint` is accepted as valid entry.

PR-URL: https://github.com/nodejs/node/pull/28173
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
This commit is contained in:
Ruben Bridgewater 2019-06-11 15:38:07 +02:00
parent 63a0f4cdd3
commit ed8fc7e11d
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
62 changed files with 1962 additions and 395 deletions

View File

@ -37,6 +37,5 @@ function main({ n, type }) {
break;
}
// eslint-disable-next-line valid-typeof
assert.ok(Array.isArray(noDead) || typeof noDead === 'bigint');
}

View File

@ -43,7 +43,6 @@ function checkBounds(buf, offset, byteLength) {
function checkInt(value, min, max, buf, offset, byteLength) {
if (value > max || value < min) {
// eslint-disable-next-line valid-typeof
const n = typeof min === 'bigint' ? 'n' : '';
let range;
if (byteLength > 3) {

View File

@ -1044,7 +1044,6 @@ E('ERR_OUT_OF_RANGE',
let received;
if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) {
received = addNumericalSeparator(String(input));
// eslint-disable-next-line valid-typeof
} else if (typeof input === 'bigint') {
received = String(input);
if (input > 2n ** 32n || input < -(2n ** 32n)) {

View File

@ -1037,7 +1037,6 @@ function groupArrayElements(ctx, output, value) {
let order = 'padStart';
if (value !== undefined) {
for (let i = 0; i < output.length; i++) {
// eslint-disable-next-line valid-typeof
if (typeof value[i] !== 'number' && typeof value[i] !== 'bigint') {
order = 'padEnd';
break;
@ -1112,7 +1111,6 @@ function formatPrimitive(fn, value, ctx) {
}
if (typeof value === 'number')
return formatNumber(fn, value);
// eslint-disable-next-line valid-typeof
if (typeof value === 'bigint')
return formatBigInt(fn, value);
if (typeof value === 'boolean')
@ -1575,7 +1573,6 @@ function formatWithOptions(inspectOptions, ...args) {
const tempArg = args[++a];
if (typeof tempArg === 'number') {
tempStr = formatNumber(stylizeNoColor, tempArg);
// eslint-disable-next-line valid-typeof
} else if (typeof tempArg === 'bigint') {
tempStr = `${tempArg}n`;
} else {
@ -1607,7 +1604,6 @@ function formatWithOptions(inspectOptions, ...args) {
break;
case 100: // 'd'
const tempNum = args[++a];
// eslint-disable-next-line valid-typeof
if (typeof tempNum === 'bigint') {
tempStr = `${tempNum}n`;
} else if (typeof tempNum === 'symbol') {
@ -1631,7 +1627,6 @@ function formatWithOptions(inspectOptions, ...args) {
}
case 105: // 'i'
const tempInteger = args[++a];
// eslint-disable-next-line valid-typeof
if (typeof tempInteger === 'bigint') {
tempStr = `${tempInteger}n`;
} else if (typeof tempInteger === 'symbol') {

View File

@ -239,9 +239,6 @@ const pwdCommand = isWindows ?
function platformTimeout(ms) {
// ESLint will not support 'bigint' in valid-typeof until it reaches stage 4.
// See https://github.com/eslint/eslint/pull/9636.
// eslint-disable-next-line valid-typeof
const multipliers = typeof ms === 'bigint' ?
{ two: 2n, four: 4n, seven: 7n } : { two: 2, four: 4, seven: 7 };

13
tools/node_modules/eslint/README.md generated vendored
View File

@ -1,6 +1,5 @@
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Build status][appveyor-image]][appveyor-url]
[![Build Status](https://dev.azure.com/eslint/eslint/_apis/build/status/eslint.eslint?branchName=master)](https://dev.azure.com/eslint/eslint/_build/latest?definitionId=1&branchName=master)
[![Downloads][downloads-image]][downloads-url]
[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=282608)](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE)
[![Join the chat at https://gitter.im/eslint/eslint](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@ -259,9 +258,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
<!--sponsorsstart-->
<h3>Gold Sponsors</h3>
<p><a href="http://salesforce.com"><img src="https://images.opencollective.com/salesforce/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/logo.png" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/fbopensource/logo.png" alt="Facebook Open Source" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/logo.png" alt="Badoo" height="96"></a> <a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/logo.png" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/logo.png" alt="Shopify" height="96"></a> <a href="http://salesforce.com"><img src="https://images.opencollective.com/salesforce/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/logo.png" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/fbopensource/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://usave.co.uk/utilities/broadband/"><img src="https://images.opencollective.com/usave/logo.png" alt="Usave" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/logo.png" alt="TekHattan" height="32"></a> <a href="https://faithlife.com/ref/about"><img src="https://images.opencollective.com/faithlife/logo.png" alt="Faithlife" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/logo.png" alt="Marfeel" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/logo.png" alt="Discord" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/logo.png" alt="JSHeroes " height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
<p><a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/logo.png" alt="JSHeroes " height="32"></a> <a href="https://faithlife.com/ref/about"><img src="https://images.opencollective.com/faithlife/logo.png" alt="Faithlife" height="32"></a></p>
<!--sponsorsend-->
## <a name="technology-sponsors"></a>Technology Sponsors
@ -271,11 +270,5 @@ The following companies, organizations, and individuals support ESLint's ongoing
[npm-image]: https://img.shields.io/npm/v/eslint.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/eslint
[travis-image]: https://img.shields.io/travis/eslint/eslint/master.svg?style=flat-square
[travis-url]: https://travis-ci.org/eslint/eslint
[appveyor-image]: https://ci.appveyor.com/api/projects/status/iwxmiobcvbw3b0av/branch/master?svg=true
[appveyor-url]: https://ci.appveyor.com/project/nzakas/eslint/branch/master
[coveralls-image]: https://img.shields.io/coveralls/eslint/eslint/master.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/eslint/eslint?branch=master
[downloads-image]: https://img.shields.io/npm/dm/eslint.svg?style=flat-square
[downloads-url]: https://www.npmjs.com/package/eslint

View File

@ -45,7 +45,7 @@ process.once("uncaughtException", err => {
const pkg = require("../package.json");
console.error("\nOops! Something went wrong! :(");
console.error(`\nESLint: ${pkg.version}.\n${template(err.messageData || {})}`);
console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
} else {
console.error(err.stack);

View File

@ -27,7 +27,7 @@ const os = require("os");
const path = require("path");
const { validateConfigArray } = require("../shared/config-validator");
const { ConfigArrayFactory } = require("./config-array-factory");
const { ConfigDependency } = require("./config-array");
const { ConfigArray, ConfigDependency } = require("./config-array");
const loadRules = require("./load-rules");
const debug = require("debug")("eslint:cascading-config-array-factory");
@ -225,11 +225,22 @@ class CascadingConfigArrayFactory {
/**
* Get the config array of a given file.
* @param {string} filePath The file path to a 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.
* @returns {ConfigArray} The config array of the file.
*/
getConfigArrayForFile(filePath) {
const { cwd } = internalSlotsMap.get(this);
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}.`);
@ -302,6 +313,7 @@ class CascadingConfigArrayFactory {
if (configArray.length > 0 && configArray.isRoot()) {
debug("Stop traversing because of 'root:true'.");
configArray.unshift(...baseConfigArray);
return this._cacheConfig(directoryPath, configArray);
}

View File

@ -573,7 +573,7 @@ class CLIEngine {
const linter = new Linter();
/** @type {ConfigArray[]} */
const lastConfigArrays = [];
const lastConfigArrays = [configArrayFactory.getConfigArrayForFile()];
// Store private data.
internalSlotsMap.set(this, {
@ -904,6 +904,13 @@ class CLIEngine {
const { configArrayFactory, options } = internalSlotsMap.get(this);
const absolutePath = path.resolve(options.cwd, filePath);
if (directoryExists(absolutePath)) {
throw Object.assign(
new Error("'filePath' should not be a directory path."),
{ messageTemplate: "print-config-with-directory-path" }
);
}
return configArrayFactory
.getConfigArrayForFile(absolutePath)
.extractConfig(absolutePath)

View File

@ -224,15 +224,16 @@ function loadPackageJSONConfigFile(filePath) {
/**
* Creates an error to notify about a missing config to extend from.
* @param {string} configName The name of the missing config.
* @param {string} importerName The name of the config that imported the missing config
* @returns {Error} The error object to throw
* @private
*/
function configMissingError(configName) {
function configMissingError(configName, importerName) {
return Object.assign(
new Error(`Failed to load config "${configName}" to extend from.`),
{
messageTemplate: "extend-config-missing",
messageData: { configName }
messageData: { configName, importerName }
}
);
}
@ -637,7 +638,7 @@ class ConfigArrayFactory {
return this._loadConfigData(eslintAllPath, name);
}
throw configMissingError(extendName);
throw configMissingError(extendName, importerName);
}
/**
@ -670,7 +671,7 @@ class ConfigArrayFactory {
);
}
throw plugin.error || configMissingError(extendName);
throw plugin.error || configMissingError(extendName, importerPath);
}
/**
@ -704,7 +705,7 @@ class ConfigArrayFactory {
} catch (error) {
/* istanbul ignore else */
if (error && error.code === "MODULE_NOT_FOUND") {
throw configMissingError(extendName);
throw configMissingError(extendName, importerPath);
}
throw error;
}

View File

@ -231,7 +231,6 @@ function mergeRuleConfigs(target, source) {
* @returns {ExtractedConfig} The extracted config.
*/
function createConfig(instance, indices) {
const slots = internalSlotsMap.get(instance);
const config = new ExtractedConfig();
// Merge elements.
@ -256,7 +255,7 @@ function createConfig(instance, indices) {
mergeWithoutOverwrite(config.globals, element.globals);
mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
mergeWithoutOverwrite(config.settings, element.settings);
mergePlugins(config.plugins, element.plugins, slots);
mergePlugins(config.plugins, element.plugins);
mergeRuleConfigs(config.rules, element.rules);
}

View File

@ -55,7 +55,17 @@ function toMatcher(patterns) {
if (patterns.length === 0) {
return null;
}
return patterns.map(pattern => new Minimatch(pattern, minimatchOpts));
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);
});
}
/**

View File

@ -5,6 +5,7 @@
"use strict";
const xmlEscape = require("../xml-escape");
const path = require("path");
//------------------------------------------------------------------------------
// Helper Functions
@ -24,6 +25,16 @@ function getMessageType(message) {
}
/**
* Returns a full file path without extension
* @param {string} filePath input file path
* @returns {string} file path without extension
* @private
*/
function pathWithoutExt(filePath) {
return path.posix.join(path.posix.dirname(filePath), path.basename(filePath, path.extname(filePath)));
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
@ -38,13 +49,14 @@ module.exports = function(results) {
results.forEach(result => {
const messages = result.messages;
const classname = pathWithoutExt(result.filePath);
if (messages.length > 0) {
output += `<testsuite package="org.eslint" time="0" tests="${messages.length}" errors="${messages.length}" name="${result.filePath}">\n`;
messages.forEach(message => {
const type = message.fatal ? "error" : "failure";
output += `<testcase time="0" name="org.eslint.${message.ruleId || "unknown"}">`;
output += `<testcase time="0" name="org.eslint.${message.ruleId || "unknown"}" classname="${classname}">`;
output += `<${type} message="${xmlEscape(message.message || "")}">`;
output += "<![CDATA[";
output += `line ${message.line || 0}, col `;
@ -58,7 +70,7 @@ module.exports = function(results) {
output += "</testsuite>\n";
} else {
output += `<testsuite package="org.eslint" time="0" tests="1" errors="0" name="${result.filePath}">\n`;
output += `<testcase time="0" name="${result.filePath}" />\n`;
output += `<testcase time="0" name="${result.filePath}" classname="${classname}" />\n`;
output += "</testsuite>\n";
}

View File

@ -929,13 +929,11 @@ function getEnv(slots, envId) {
* Get a rule.
* @param {LinterInternalSlots} slots The internal slots of Linter.
* @param {string} ruleId The rule ID to get.
* @returns {Rule} The rule.
* @returns {Rule|null} The rule.
*/
function getRule(slots, ruleId) {
return (
(slots.lastConfigArray && slots.lastConfigArray.pluginRules.get(ruleId)) ||
// This returns the stub for missing rules if the rule does not exist.
slots.ruleMap.get(ruleId)
);
}

View File

@ -221,17 +221,19 @@ class NodeEventGenerator {
const selector = parseSelector(rawSelector);
if (selector.listenerTypes) {
selector.listenerTypes.forEach(nodeType => {
const typeMap = selector.isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType;
const typeMap = selector.isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType;
selector.listenerTypes.forEach(nodeType => {
if (!typeMap.has(nodeType)) {
typeMap.set(nodeType, []);
}
typeMap.get(nodeType).push(selector);
});
} else {
(selector.isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors).push(selector);
return;
}
const selectors = selector.isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors;
selectors.push(selector);
});
this.anyTypeEnterSelectors.sort(compareSpecificity);

View File

@ -123,6 +123,18 @@ function freezeDeeply(x) {
}
}
/**
* Replace control characters by `\u00xx` form.
* @param {string} text The text to sanitize.
* @returns {string} The sanitized text.
*/
function sanitize(text) {
return text.replace(
/[\u0000-\u001f]/gu, // eslint-disable-line no-control-regex
c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`
);
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
@ -313,7 +325,7 @@ class RuleTester {
*/
function runRuleForItem(item) {
let config = lodash.cloneDeep(testerConfig),
code, filename, beforeAST, afterAST;
code, filename, output, beforeAST, afterAST;
if (typeof item === "string") {
code = item;
@ -396,8 +408,29 @@ class RuleTester {
validate(config, "rule-tester", id => (id === ruleName ? rule : null));
// Verify the code.
const messages = linter.verify(code, config, filename);
// Ignore syntax errors for backward compatibility if `errors` is a number.
if (typeof item.errors !== "number") {
const errorMessage = messages.find(m => m.fatal);
assert(!errorMessage, `A fatal parsing error occurred: ${errorMessage && errorMessage.message}`);
}
// Verify if autofix makes a syntax error or not.
if (messages.some(m => m.fix)) {
output = SourceCodeFixer.applyFixes(code, messages).output;
const errorMessageInFix = linter.verify(output, config, filename).find(m => m.fatal);
assert(!errorMessageInFix, `A fatal parsing error occurred in autofix: ${errorMessageInFix && errorMessageInFix.message}`);
} else {
output = code;
}
return {
messages: linter.verify(code, config, filename, true),
messages,
output,
beforeAST,
afterAST: cloneDeeplyExcludesParent(afterAST)
};
@ -488,7 +521,6 @@ class RuleTester {
const error = item.errors[i];
const message = messages[i];
assert(!message.fatal, `A fatal parsing error occurred: ${message.message}`);
assert(hasMessageOfThisRule, "Error rule name should be the same as the name of the rule being tested");
if (typeof error === "string" || error instanceof RegExp) {
@ -574,14 +606,12 @@ class RuleTester {
if (Object.prototype.hasOwnProperty.call(item, "output")) {
if (item.output === null) {
assert.strictEqual(
messages.filter(message => message.fix).length,
0,
result.output,
item.code,
"Expected no autofixes to be suggested"
);
} else {
const fixResult = SourceCodeFixer.applyFixes(item.code, messages);
assert.strictEqual(fixResult.output, item.output, "Output is incorrect.");
assert.strictEqual(result.output, item.output, "Output is incorrect.");
}
}
@ -595,7 +625,7 @@ class RuleTester {
RuleTester.describe(ruleName, () => {
RuleTester.describe("valid", () => {
test.valid.forEach(valid => {
RuleTester.it(typeof valid === "object" ? valid.code : valid, () => {
RuleTester.it(sanitize(typeof valid === "object" ? valid.code : valid), () => {
testValidTemplate(valid);
});
});
@ -603,7 +633,7 @@ class RuleTester {
RuleTester.describe("invalid", () => {
test.invalid.forEach(invalid => {
RuleTester.it(invalid.code, () => {
RuleTester.it(sanitize(invalid.code), () => {
testInvalidTemplate(invalid);
});
});

View File

@ -10,6 +10,23 @@
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Get location should be reported by AST node.
*
* @param {ASTNode} node AST Node.
* @returns {Location} Location information.
*/
function getLocation(node) {
return {
start: node.params[0].loc.start,
end: node.params[node.params.length - 1].loc.end
};
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@ -102,6 +119,7 @@ module.exports = {
context.report({
node,
messageId: "unexpectedParensInline",
loc: getLocation(node),
fix: fixParamsWithParenthesis
});
}
@ -116,6 +134,7 @@ module.exports = {
context.report({
node,
messageId: "expectedParensBlock",
loc: getLocation(node),
fix(fixer) {
return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
}
@ -135,6 +154,7 @@ module.exports = {
context.report({
node,
messageId: "unexpectedParens",
loc: getLocation(node),
fix: fixParamsWithParenthesis
});
}
@ -149,6 +169,7 @@ module.exports = {
context.report({
node,
messageId: "expectedParens",
loc: getLocation(node),
fix(fixer) {
return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
}

View File

@ -315,6 +315,13 @@ module.exports = {
textToMeasure = line;
} else if (ignoreTrailingComments && isTrailingComment(line, lineNumber, comment)) {
textToMeasure = stripTrailingComment(line, comment);
// ignore multiple trailing comments in the same line
let lastIndex = commentsIndex;
while (isTrailingComment(textToMeasure, lineNumber, comments[--lastIndex])) {
textToMeasure = stripTrailingComment(textToMeasure, comments[lastIndex]);
}
} else {
textToMeasure = line;
}

View File

@ -25,6 +25,7 @@ module.exports = {
schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }],
messages: {
expectedBlock: "Expected a block comment instead of consecutive line comments.",
expectedBareBlock: "Expected a block comment without padding stars.",
startNewline: "Expected a linebreak after '/*'.",
endNewline: "Expected a linebreak before '*/'.",
missingStar: "Expected a '*' at the start of this line.",
@ -250,7 +251,7 @@ module.exports = {
start: block.loc.start,
end: { line: block.loc.start.line, column: block.loc.start.column + 2 }
},
messageId: "expectedBlock",
messageId: "expectedBareBlock",
fix(fixer) {
return fixer.replaceText(block, convertToBlock(block, commentLines.filter(line => line)));
}

View File

@ -51,6 +51,124 @@ module.exports = {
// Helpers
//--------------------------------------------------------------------------
/**
* Checks whether the given names can be safely used to declare block-scoped variables
* in the given scope. Name collisions can produce redeclaration syntax errors,
* or silently change references and modify behavior of the original code.
*
* This is not a generic function. In particular, it is assumed that the scope is a function scope or
* a function's inner scope, and that the names can be valid identifiers in the given scope.
*
* @param {string[]} names Array of variable names.
* @param {eslint-scope.Scope} scope Function scope or a function's inner scope.
* @returns {boolean} True if all names can be safely declared, false otherwise.
*/
function isSafeToDeclare(names, scope) {
if (names.length === 0) {
return true;
}
const functionScope = scope.variableScope;
/*
* If this is a function scope, scope.variables will contain parameters, implicit variables such as "arguments",
* all function-scoped variables ('var'), and block-scoped variables defined in the scope.
* If this is an inner scope, scope.variables will contain block-scoped variables defined in the scope.
*
* Redeclaring any of these would cause a syntax error, except for the implicit variables.
*/
const declaredVariables = scope.variables.filter(({ defs }) => defs.length > 0);
if (declaredVariables.some(({ name }) => names.includes(name))) {
return false;
}
// Redeclaring a catch variable would also cause a syntax error.
if (scope !== functionScope && scope.upper.type === "catch") {
if (scope.upper.variables.some(({ name }) => names.includes(name))) {
return false;
}
}
/*
* Redeclaring an implicit variable, such as "arguments", would not cause a syntax error.
* However, if the variable was used, declaring a new one with the same name would change references
* and modify behavior.
*/
const usedImplicitVariables = scope.variables.filter(({ defs, references }) =>
defs.length === 0 && references.length > 0);
if (usedImplicitVariables.some(({ name }) => names.includes(name))) {
return false;
}
/*
* Declaring a variable with a name that was already used to reference a variable from an upper scope
* would change references and modify behavior.
*/
if (scope.through.some(t => names.includes(t.identifier.name))) {
return false;
}
/*
* If the scope is an inner scope (not the function scope), an uninitialized `var` variable declared inside
* the scope node (directly or in one of its descendants) is neither declared nor 'through' in the scope.
*
* For example, this would be a syntax error "Identifier 'a' has already been declared":
* function foo() { if (bar) { let a; if (baz) { var a; } } }
*/
if (scope !== functionScope) {
const scopeNodeRange = scope.block.range;
const variablesToCheck = functionScope.variables.filter(({ name }) => names.includes(name));
if (variablesToCheck.some(v => v.defs.some(({ node: { range } }) =>
scopeNodeRange[0] <= range[0] && range[1] <= scopeNodeRange[1]))) {
return false;
}
}
return true;
}
/**
* Checks whether the removal of `else` and its braces is safe from variable name collisions.
*
* @param {Node} node The 'else' node.
* @param {eslint-scope.Scope} scope The scope in which the node and the whole 'if' statement is.
* @returns {boolean} True if it is safe, false otherwise.
*/
function isSafeFromNameCollisions(node, scope) {
if (node.type === "FunctionDeclaration") {
// Conditional function declaration. Scope and hoisting are unpredictable, different engines work differently.
return false;
}
if (node.type !== "BlockStatement") {
return true;
}
const elseBlockScope = scope.childScopes.find(({ block }) => block === node);
if (!elseBlockScope) {
// ecmaVersion < 6, `else` block statement cannot have its own scope, no possible collisions.
return true;
}
/*
* elseBlockScope is supposed to merge into its upper scope. elseBlockScope.variables array contains
* only block-scoped variables (such as let and const variables or class and function declarations)
* defined directly in the elseBlockScope. These are exactly the only names that could cause collisions.
*/
const namesToCheck = elseBlockScope.variables.map(({ name }) => name);
return isSafeToDeclare(namesToCheck, scope);
}
/**
* Display the context report if rule is violated
*
@ -58,10 +176,17 @@ module.exports = {
* @returns {void}
*/
function displayReport(node) {
const currentScope = context.getScope();
context.report({
node,
messageId: "unexpected",
fix: fixer => {
if (!isSafeFromNameCollisions(node, currentScope)) {
return null;
}
const sourceCode = context.getSourceCode();
const startToken = sourceCode.getFirstToken(node);
const elseToken = sourceCode.getTokenBefore(startToken);
@ -118,6 +243,8 @@ module.exports = {
* Extend the replacement range to include the entire
* function to avoid conflicting with no-useless-return.
* https://github.com/eslint/eslint/issues/8026
*
* Also, to avoid name collisions between two else blocks.
*/
return new FixTracker(fixer, sourceCode)
.retainEnclosingFunction(node)

View File

@ -28,7 +28,7 @@ module.exports = {
return {
Literal(node) {
if (typeof node.value === "number" && /^0[0-7]/u.test(node.raw)) {
if (typeof node.value === "number" && /^0[0-9]/u.test(node.raw)) {
context.report({ node, message: "Octal literals should not be used." });
}
}

View File

@ -4,13 +4,6 @@
*/
"use strict";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const DEFAULT_MESSAGE_TEMPLATE = "'{{importSource}}' import is restricted from being used.";
const CUSTOM_MESSAGE_TEMPLATE = "'{{importSource}}' import is restricted from being used. {{customMessage}}";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@ -62,6 +55,18 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-restricted-imports"
},
messages: {
path: "'{{importSource}}' import is restricted from being used.",
// eslint-disable-next-line eslint-plugin/report-message-format
pathWithCustomMessage: "'{{importSource}}' import is restricted from being used. {{customMessage}}",
patterns: "'{{importSource}}' import is restricted from being used by a pattern.",
everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
// eslint-disable-next-line eslint-plugin/report-message-format
everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}"
},
schema: {
anyOf: [
arrayOfStringsOrObjects,
@ -127,13 +132,10 @@ module.exports = {
function reportPath(node) {
const importSource = node.source.value.trim();
const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
const message = customMessage
? CUSTOM_MESSAGE_TEMPLATE
: DEFAULT_MESSAGE_TEMPLATE;
context.report({
node,
message,
messageId: customMessage ? "pathWithCustomMessage" : "path",
data: {
importSource,
customMessage
@ -152,7 +154,7 @@ module.exports = {
context.report({
node,
message: "'{{importSource}}' import is restricted from being used by a pattern.",
messageId: "patterns",
data: {
importSource
}
@ -168,13 +170,15 @@ module.exports = {
*/
function reportPathForEverythingImported(importSource, node) {
const importNames = restrictedPathMessages[importSource].importNames;
const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
context.report({
node,
message: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
messageId: customMessage ? "everythingWithCustomMessage" : "everything",
data: {
importSource,
importNames
importNames,
customMessage
}
});
}

View File

@ -102,9 +102,14 @@ module.exports = {
* @returns {void}
*/
function report(node, startOffset, character) {
const start = sourceCode.getLocFromIndex(sourceCode.getIndexFromLoc(node.loc.start) + startOffset);
context.report({
node,
loc: sourceCode.getLocFromIndex(sourceCode.getIndexFromLoc(node.loc.start) + startOffset),
loc: {
start,
end: { line: start.line, column: start.column + 1 }
},
message: "Unnecessary escape character: \\{{character}}.",
data: { character }
});

View File

@ -174,6 +174,17 @@ function hasReferenceInTDZ(node) {
};
}
/**
* Checks whether a given variable has name that is allowed for 'var' declarations,
* but disallowed for `let` declarations.
*
* @param {eslint-scope.Variable} variable The variable to check.
* @returns {boolean} `true` if the variable has a disallowed name.
*/
function hasNameDisallowedForLetDeclarations(variable) {
return variable.name === "let";
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@ -223,6 +234,7 @@ module.exports = {
* - A variable might be used before it is assigned within a loop.
* - A variable might be used in TDZ.
* - A variable is declared in statement position (e.g. a single-line `IfStatement`)
* - A variable has name that is disallowed for `let` declarations.
*
* ## A variable is declared on a SwitchCase node.
*
@ -271,7 +283,8 @@ module.exports = {
node.declarations.some(hasSelfReferenceInTDZ) ||
variables.some(isGlobal) ||
variables.some(isRedeclared) ||
variables.some(isUsedFromOutsideOf(scopeNode))
variables.some(isUsedFromOutsideOf(scopeNode)) ||
variables.some(hasNameDisallowedForLetDeclarations)
) {
return false;
}

View File

@ -24,12 +24,51 @@ function createReferenceMap(scope, outReferenceMap = new Map()) {
return outReferenceMap;
}
/**
* Get `reference.writeExpr` of a given reference.
* If it's the read reference of MemberExpression in LHS, returns RHS in order to address `a.b = await a`
* @param {escope.Reference} reference The reference to get.
* @returns {Expression|null} The `reference.writeExpr`.
*/
function getWriteExpr(reference) {
if (reference.writeExpr) {
return reference.writeExpr;
}
let node = reference.identifier;
while (node) {
const t = node.parent.type;
if (t === "AssignmentExpression" && node.parent.left === node) {
return node.parent.right;
}
if (t === "MemberExpression" && node.parent.object === node) {
node = node.parent;
continue;
}
break;
}
return null;
}
/**
* Checks if an expression is a variable that can only be observed within the given function.
* @param {escope.Variable} variable The variable to check
* @param {Variable|null} variable The variable to check
* @param {boolean} isMemberAccess If `true` then this is a member access.
* @returns {boolean} `true` if the variable is local to the given function, and is never referenced in a closure.
*/
function isLocalVariableWithoutEscape(variable) {
function isLocalVariableWithoutEscape(variable, isMemberAccess) {
if (!variable) {
return false; // A global variable which was not defined.
}
// If the reference is a property access and the variable is a parameter, it handles the variable is not local.
if (isMemberAccess && variable.defs.some(d => d.type === "Parameter")) {
return false;
}
const functionScope = variable.scope.variableScope;
return variable.references.every(reference =>
@ -47,52 +86,49 @@ class SegmentInfo {
* @returns {void}
*/
initialize(segment) {
const outdatedReadVariables = new Set();
const freshReadVariables = new Set();
const outdatedReadVariableNames = new Set();
const freshReadVariableNames = new Set();
for (const prevSegment of segment.prevSegments) {
const info = this.info.get(prevSegment);
if (info) {
info.outdatedReadVariables.forEach(Set.prototype.add, outdatedReadVariables);
info.freshReadVariables.forEach(Set.prototype.add, freshReadVariables);
info.outdatedReadVariableNames.forEach(Set.prototype.add, outdatedReadVariableNames);
info.freshReadVariableNames.forEach(Set.prototype.add, freshReadVariableNames);
}
}
this.info.set(segment, { outdatedReadVariables, freshReadVariables });
this.info.set(segment, { outdatedReadVariableNames, freshReadVariableNames });
}
/**
* Mark a given variable as read on given segments.
* @param {PathSegment[]} segments The segments that it read the variable on.
* @param {escope.Variable} variable The variable to be read.
* @param {string} variableName The variable name to be read.
* @returns {void}
*/
markAsRead(segments, variable) {
markAsRead(segments, variableName) {
for (const segment of segments) {
const info = this.info.get(segment);
if (info) {
info.freshReadVariables.add(variable);
info.freshReadVariableNames.add(variableName);
}
}
}
/**
* Move `freshReadVariables` to `outdatedReadVariables`.
* Move `freshReadVariableNames` to `outdatedReadVariableNames`.
* @param {PathSegment[]} segments The segments to process.
* @returns {void}
*/
makeOutdated(segments) {
const vars = new Set();
for (const segment of segments) {
const info = this.info.get(segment);
if (info) {
info.freshReadVariables.forEach(Set.prototype.add, info.outdatedReadVariables);
info.freshReadVariables.forEach(Set.prototype.add, vars);
info.freshReadVariables.clear();
info.freshReadVariableNames.forEach(Set.prototype.add, info.outdatedReadVariableNames);
info.freshReadVariableNames.clear();
}
}
}
@ -100,14 +136,14 @@ class SegmentInfo {
/**
* Check if a given variable is outdated on the current segments.
* @param {PathSegment[]} segments The current segments.
* @param {escope.Variable} variable The variable to check.
* @param {string} variableName The variable name to check.
* @returns {boolean} `true` if the variable is outdated on the segments.
*/
isOutdated(segments, variable) {
isOutdated(segments, variableName) {
for (const segment of segments) {
const info = this.info.get(segment);
if (info && info.outdatedReadVariables.has(variable)) {
if (info && info.outdatedReadVariableNames.has(variableName)) {
return true;
}
}
@ -140,69 +176,10 @@ module.exports = {
create(context) {
const sourceCode = context.getSourceCode();
const globalScope = context.getScope();
const dummyVariables = new Map();
const assignmentReferences = new Map();
const segmentInfo = new SegmentInfo();
let stack = null;
/**
* Get the variable of a given reference.
* If it's not defined, returns a dummy object.
* @param {escope.Reference} reference The reference to get.
* @returns {escope.Variable} The variable of the reference.
*/
function getVariable(reference) {
if (reference.resolved) {
return reference.resolved;
}
// Get or create a dummy.
const name = reference.identifier.name;
let variable = dummyVariables.get(name);
if (!variable) {
variable = {
name,
scope: globalScope,
references: []
};
dummyVariables.set(name, variable);
}
variable.references.push(reference);
return variable;
}
/**
* Get `reference.writeExpr` of a given reference.
* If it's the read reference of MemberExpression in LHS, returns RHS in order to address `a.b = await a`
* @param {escope.Reference} reference The reference to get.
* @returns {Expression|null} The `reference.writeExpr`.
*/
function getWriteExpr(reference) {
if (reference.writeExpr) {
return reference.writeExpr;
}
let node = reference.identifier;
while (node) {
const t = node.parent.type;
if (t === "AssignmentExpression" && node.parent.left === node) {
return node.parent.right;
}
if (t === "MemberExpression" && node.parent.object === node) {
node = node.parent;
continue;
}
break;
}
return null;
}
return {
onCodePathStart(codePath) {
const scope = context.getScope();
@ -234,12 +211,14 @@ module.exports = {
if (!reference) {
return;
}
const variable = getVariable(reference);
const name = reference.identifier.name;
const variable = reference.resolved;
const writeExpr = getWriteExpr(reference);
const isMemberAccess = reference.identifier.parent.type === "MemberExpression";
// Add a fresh read variable.
if (reference.isRead() && !(writeExpr && writeExpr.parent.operator === "=")) {
segmentInfo.markAsRead(codePath.currentSegments, variable);
segmentInfo.markAsRead(codePath.currentSegments, name);
}
/*
@ -248,7 +227,7 @@ module.exports = {
*/
if (writeExpr &&
writeExpr.parent.right === writeExpr && // ← exclude variable declarations.
!isLocalVariableWithoutEscape(variable)
!isLocalVariableWithoutEscape(variable, isMemberAccess)
) {
let refs = assignmentReferences.get(writeExpr);
@ -263,7 +242,7 @@ module.exports = {
/*
* Verify assignments.
* If the reference exists in `outdatedReadVariables` list, report it.
* If the reference exists in `outdatedReadVariableNames` list, report it.
*/
":expression:exit"(node) {
const { codePath, referenceMap } = stack;
@ -285,9 +264,9 @@ module.exports = {
assignmentReferences.delete(node);
for (const reference of references) {
const variable = getVariable(reference);
const name = reference.identifier.name;
if (segmentInfo.isOutdated(codePath.currentSegments, variable)) {
if (segmentInfo.isOutdated(codePath.currentSegments, name)) {
context.report({
node: node.parent,
messageId: "nonAtomicUpdate",

View File

@ -96,6 +96,11 @@ module.exports = {
natural: {
type: "boolean",
default: false
},
minKeys: {
type: "integer",
minimum: 2,
default: 2
}
},
additionalProperties: false
@ -110,6 +115,7 @@ module.exports = {
const options = context.options[1];
const insensitive = options && options.caseSensitive === false;
const natual = options && options.natural;
const minKeys = options && options.minKeys;
const isValidOrder = isValidOrders[
order + (insensitive ? "I" : "") + (natual ? "N" : "")
];
@ -118,10 +124,11 @@ module.exports = {
let stack = null;
return {
ObjectExpression() {
ObjectExpression(node) {
stack = {
upper: stack,
prevName: null
prevName: null,
numKeys: node.properties.length
};
},
@ -141,11 +148,12 @@ module.exports = {
}
const prevName = stack.prevName;
const numKeys = stack.numKeys;
const thisName = getPropertyName(node);
stack.prevName = thisName || prevName;
if (!prevName || !thisName) {
if (!prevName || !thisName || numKeys < minKeys) {
return;
}

View File

@ -39,7 +39,7 @@ module.exports = {
create(context) {
const VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"],
const VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function", "bigint"],
OPERATORS = ["==", "===", "!=", "!=="];
const requireStringLiterals = context.options[0] && context.options[0].requireStringLiterals;

View File

@ -1,3 +1,5 @@
ESLint couldn't find the config "<%- configName %>" to extend from. Please check that the name of the config is correct.
The config "<%- configName %>" was referenced from the config file in "<%- importerName %>".
If you still have problems, please stop by https://gitter.im/eslint/eslint to chat with the team.

View File

@ -0,0 +1,2 @@
The '--print-config' CLI option requires a path to a source code file rather than a directory.
See also: https://eslint.org/docs/user-guide/command-line-interface#--print-config

View File

@ -66,5 +66,5 @@
"publish-release": "eslint-publish-release",
"test": "npm run-script lint && node Makefile.js test"
},
"version": "6.0.0-alpha.0"
"version": "6.0.0"
}

View File

@ -0,0 +1,174 @@
{
"es3": true,
"additionalRules": [],
"requireSemicolons": true,
"disallowMultipleSpaces": true,
"disallowIdentifierNames": [],
"requireCurlyBraces": {
"allExcept": [],
"keywords": ["if", "else", "for", "while", "do", "try", "catch"]
},
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"],
"disallowSpaceAfterKeywords": [],
"disallowSpaceBeforeComma": true,
"disallowSpaceAfterComma": false,
"disallowSpaceBeforeSemicolon": true,
"disallowNodeTypes": [
"DebuggerStatement",
"LabeledStatement",
"SwitchCase",
"SwitchStatement",
"WithStatement"
],
"requireObjectKeysOnNewLine": { "allExcept": ["sameLine"] },
"requireSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true },
"requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true },
"disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true },
"requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true },
"disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true },
"requireSpaceBetweenArguments": true,
"disallowSpacesInsideParentheses": true,
"disallowSpacesInsideArrayBrackets": true,
"disallowQuotedKeysInObjects": { "allExcept": ["reserved"] },
"disallowSpaceAfterObjectKeys": true,
"requireCommaBeforeLineBreak": true,
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
"requireSpaceAfterPrefixUnaryOperators": [],
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
"requireSpaceBeforePostfixUnaryOperators": [],
"disallowSpaceBeforeBinaryOperators": [],
"requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
"requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
"disallowSpaceAfterBinaryOperators": [],
"disallowImplicitTypeConversion": ["binary", "string"],
"disallowKeywords": ["with", "eval"],
"requireKeywordsOnNewLine": [],
"disallowKeywordsOnNewLine": ["else"],
"requireLineFeedAtFileEnd": true,
"disallowTrailingWhitespace": true,
"disallowTrailingComma": true,
"excludeFiles": ["node_modules/**", "vendor/**"],
"disallowMultipleLineStrings": true,
"requireDotNotation": { "allExcept": ["keywords"] },
"requireParenthesesAroundIIFE": true,
"validateLineBreaks": "LF",
"validateQuoteMarks": {
"escape": true,
"mark": "'"
},
"disallowOperatorBeforeLineBreak": [],
"requireSpaceBeforeKeywords": [
"do",
"for",
"if",
"else",
"switch",
"case",
"try",
"catch",
"finally",
"while",
"with",
"return"
],
"validateAlignedFunctionParameters": {
"lineBreakAfterOpeningBraces": true,
"lineBreakBeforeClosingBraces": true
},
"requirePaddingNewLinesBeforeExport": true,
"validateNewlineAfterArrayElements": {
"maximum": 6
},
"requirePaddingNewLinesAfterUseStrict": true,
"disallowArrowFunctions": true,
"disallowMultiLineTernary": true,
"validateOrderInObjectKeys": false,
"disallowIdenticalDestructuringNames": true,
"disallowNestedTernaries": { "maxLevel": 1 },
"requireSpaceAfterComma": { "allExcept": ["trailing"] },
"requireAlignedMultilineParams": false,
"requireSpacesInGenerator": {
"afterStar": true
},
"disallowSpacesInGenerator": {
"beforeStar": true
},
"disallowVar": false,
"requireArrayDestructuring": false,
"requireEnhancedObjectLiterals": false,
"requireObjectDestructuring": false,
"requireEarlyReturn": false,
"requireCapitalizedConstructorsNew": {
"allExcept": ["Function", "String", "Object", "Symbol", "Number", "Date", "RegExp", "Error", "Boolean", "Array"]
},
"requireImportAlphabetized": false,
"requireSpaceBeforeObjectValues": true,
"requireSpaceBeforeDestructuredValues": true,
"disallowSpacesInsideTemplateStringPlaceholders": true,
"disallowArrayDestructuringReturn": false,
"requireNewlineBeforeSingleStatementsInIf": false,
"disallowUnusedVariables": true,
"requireSpacesInsideImportedObjectBraces": true,
"requireUseStrict": true
}

View File

@ -0,0 +1,94 @@
# Flatted Specifications
This document describes operations performed to produce, or parse, the flatted output.
## stringify(any) => flattedString
The output is always an `Array` that contains at index `0` the given value.
If the value is an `Array` or an `Object`, per each property value passed through the callback, return the value as is if it's not an `Array`, an `Object`, or a `string`.
In case it's an `Array`, an `Object`, or a `string`, return the index as `string`, associated through a `Map`.
Giving the following example:
```js
flatted.stringify('a'); // ["a"]
flatted.stringify(['a']); // [["1"],"a"]
flatted.stringify(['a', 1, 'b']); // [["1",1,"2"],"a","b"]
```
There is an `input` containing `[array, "a", "b"]`, where the `array` has indexes `"1"` and `"2"` as strings, indexes that point respectively at `"a"` and `"b"` within the input `[array, "a", "b"]`.
The exact same happens for objects.
```js
flatted.stringify('a'); // ["a"]
flatted.stringify({a: 'a'}); // [{"a":"1"},"a"]
flatted.stringify({a: 'a', n: 1, b: 'b'}); // [{"a":"1","n":1,"b":"2"},"a","b"]
```
Every object, string, or array, encountered during serialization will be stored once as stringified index.
```js
// per each property/value of the object/array
if (any == null || !/object|string/.test(typeof any))
return any;
if (!map.has(any)) {
const index = String(arr.length);
arr.push(any);
map.set(any, index);
}
return map.get(any);
```
This, performed before going through all properties, grants unique indexes per reference.
The stringified indexes ensure there won't be conflicts with regularly stored numbers.
## parse(flattedString) => any
Everything that is a `string` is wrapped as `new String`, but strings in the array, from index `1` on, is kept as regular `string`.
```js
const input = JSON.parse('[{"a":"1"},"b"]', Strings).map(strings);
// convert strings primitives into String instances
function Strings(key, value) {
return typeof value === 'string' ? new String(value) : value;
}
// converts String instances into strings primitives
function strings(value) {
return value instanceof String ? String(value) : value;
}
```
The `input` array will have a regular `string` at index `1`, but its object at index `0` will have an `instanceof String` as `.a` property.
That is the key to place back values from the rest of the array, so that per each property of the object at index `0`, if the value is an `instanceof` String, something not serializable via JSON, it means it can be used to retrieve the position of its value from the `input` array.
If such `value` is an object and it hasn't been parsed yet, add it as parsed and go through all its properties/values.
```js
// outside any loop ...
const parsed = new Set;
// ... per each property/value ...
if (value instanceof Primitive) {
const tmp = input[parseInt(value)];
if (typeof tmp === 'object' && !parsed.has(tmp)) {
parsed.add(tmp);
output[key] = tmp;
if (typeof tmp === 'object' && tmp != null) {
// perform this same logic per
// each nested property/value ...
}
} else {
output[key] = tmp;
}
} else
output[key] = tmp;
```
As summary, the whole logic is based on polluting the de-serialization with a kind of variable that is unexpected, hence secure to use as directive to retrieve an index with a value.
The usage of a `Map` and a `Set` to flag known references/strings as visited/stored makes **flatted** a rock solid, fast, and compact, solution.

View File

@ -114,5 +114,5 @@ var Flatted = (function (Primitive, primitive) {
}(String, 'string'));
export default Flatted;
export const parse = Flatted.parse;
export const stringify = Flatted.stringify;
export var parse = Flatted.parse;
export var stringify = Flatted.stringify;

View File

@ -1,2 +1,2 @@
/*! (c) 2018, Andrea Giammarchi, (ISC) */
var Flatted=function(a,l){return{parse:function(n,t){var e=JSON.parse(n,i).map(f),r=e[0],u=t||s,c="object"==typeof r&&r?function u(c,f,n,i){return Object.keys(n).reduce(function(n,t){var e=n[t];if(e instanceof a){var r=c[e];"object"!=typeof r||f.has(r)?n[t]=i.call(n,t,r):(f.add(r),n[t]=i.call(n,t,u(c,f,r,i)))}else n[t]=i.call(n,t,e);return n},n)}(e,new Set,r,u):r;return u.call({"":c},"",c)},stringify:function(n,e,t){for(var r,u=new Map,c=[],f=[],i=e&&typeof e==typeof c?function(n,t){if(""===n||-1<e.indexOf(n))return t}:e||s,a=+p(u,c,i.call({"":n},"",n)),o=function(n,t){if(r)return r=!r,t;var e=i.call(this,n,t);switch(typeof e){case"object":if(null===e)return e;case l:return u.get(e)||p(u,c,e)}return e};a<c.length;a++)r=!0,f[a]=JSON.stringify(c[a],o,t);return"["+f.join(",")+"]"}};function s(n,t){return t}function p(n,t,e){var r=a(t.push(e)-1);return n.set(e,r),r}function f(n){return n instanceof a?a(n):n}function i(n,t){return typeof t===l?new a(t):t}}(String,"string");
var Flatted=function(a,l){return{parse:function(n,t){var e=JSON.parse(n,i).map(f),r=e[0],u=t||s,c="object"==typeof r&&r?function u(c,f,n,i){return Object.keys(n).reduce(function(n,t){var e=n[t];if(e instanceof a){var r=c[e];"object"!=typeof r||f.has(r)?n[t]=i.call(n,t,r):(f.add(r),n[t]=i.call(n,t,u(c,f,r,i)))}else n[t]=i.call(n,t,e);return n},n)}(e,new Set,r,u):r;return u.call({"":c},"",c)},stringify:function(n,e,t){function r(n,t){if(u)return u=!u,t;var e=a.call(this,n,t);switch(typeof e){case"object":if(null===e)return e;case l:return c.get(e)||p(c,f,e)}return e}for(var u,c=new Map,f=[],i=[],a=e&&typeof e==typeof f?function(n,t){if(""===n||-1<e.indexOf(n))return t}:e||s,o=+p(c,f,a.call({"":n},"",n));o<f.length;o++)u=!0,i[o]=JSON.stringify(f[o],r,t);return"["+i.join(",")+"]"}};function s(n,t){return t}function p(n,t,e){var r=a(t.push(e)-1);return n.set(e,r),r}function f(n){return n instanceof a?a(n):n}function i(n,t){return typeof t==l?new a(t):t}}(String,"string");

View File

@ -37,12 +37,12 @@
"build": "npm run cjs && npm test && npm run esm && npm run min && npm run size",
"cjs": "cp index.js cjs/index.js; echo 'module.exports = Flatted;' >> cjs/index.js",
"coveralls": "cat ./coverage/lcov.info | coveralls",
"esm": "cp index.js esm/index.js; echo 'export default Flatted;' >> esm/index.js; echo 'export const parse = Flatted.parse;' >> esm/index.js; echo 'export const stringify = Flatted.stringify;' >> esm/index.js",
"esm": "cp index.js esm/index.js; echo 'export default Flatted;' >> esm/index.js; echo 'export var parse = Flatted.parse;' >> esm/index.js; echo 'export var stringify = Flatted.stringify;' >> esm/index.js",
"min": "echo '/*! (c) 2018, Andrea Giammarchi, (ISC) */'>min.js && uglifyjs index.js --support-ie8 -c -m >> min.js",
"size": "cat index.js | wc -c;cat min.js | wc -c;gzip -c9 min.js | wc -c;cat min.js | brotli | wc -c",
"test": "istanbul cover test/index.js"
},
"types": "types.d.ts",
"unpkg": "min.js",
"version": "2.0.0"
"version": "2.0.1"
}

View File

@ -1,7 +1,9 @@
try {
var util = require('util');
/* istanbul ignore next */
if (typeof util.inherits !== 'function') throw '';
module.exports = util.inherits;
} catch (e) {
/* istanbul ignore next */
module.exports = require('./inherits_browser.js');
}

View File

@ -1,23 +1,27 @@
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
if (superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
})
}
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
if (superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
}

View File

@ -7,7 +7,7 @@
"deprecated": false,
"description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
"devDependencies": {
"tap": "^7.1.0"
"tap": "^14.2.4"
},
"files": [
"inherits.js",
@ -32,7 +32,7 @@
"url": "git://github.com/isaacs/inherits.git"
},
"scripts": {
"test": "node test"
"test": "tap"
},
"version": "2.0.3"
"version": "2.0.4"
}

View File

@ -40,7 +40,7 @@
"lib",
"README.md"
],
"gitHead": "ee1cc700ad48f10fc304055ec733fb6be6c1d09c",
"gitHead": "b951b48e46930b3fe6300b7f42f58d3042579619",
"homepage": "https://github.com/SBoudrias/Inquirer.js#readme",
"keywords": [
"command",
@ -63,5 +63,5 @@
"prepublishOnly": "cp ../../README.md .",
"test": "nyc mocha test/**/* -r ./test/before"
},
"version": "6.3.1"
"version": "6.4.1"
}

View File

@ -28,7 +28,7 @@ module.exports = function(val, options) {
var type = typeof val;
if (type === 'string' && val.length > 0) {
return parse(val);
} else if (type === 'number' && isNaN(val) === false) {
} else if (type === 'number' && isFinite(val)) {
return options.long ? fmtLong(val) : fmtShort(val);
}
throw new Error(
@ -50,7 +50,7 @@ function parse(str) {
if (str.length > 100) {
return;
}
var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
str
);
if (!match) {

View File

@ -42,5 +42,5 @@
"precommit": "lint-staged",
"test": "mocha tests.js"
},
"version": "2.1.1"
"version": "2.1.2"
}

View File

@ -1,7 +1,7 @@
# ms
[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/zeit)
Use this package to easily convert various time formats to milliseconds.

View File

@ -172,15 +172,15 @@ config = {
columns: {
0: {
alignment: 'left',
minWidth: 10
width: 10
},
1: {
alignment: 'center',
minWidth: 10
width: 10
},
2: {
alignment: 'right',
minWidth: 10
width: 10
}
}
};

View File

@ -85,5 +85,5 @@
"lint": "npm run build && eslint ./src ./test && flow",
"test": "mocha --require @babel/register"
},
"version": "5.4.0"
"version": "5.4.1"
}

21
tools/node_modules/eslint/node_modules/tmp/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 KARASZI István
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.

314
tools/node_modules/eslint/node_modules/tmp/README.md generated vendored Normal file
View File

@ -0,0 +1,314 @@
# Tmp
A simple temporary file and directory creator for [node.js.][1]
[![Build Status](https://travis-ci.org/raszi/node-tmp.svg?branch=master)](https://travis-ci.org/raszi/node-tmp)
[![Dependencies](https://david-dm.org/raszi/node-tmp.svg)](https://david-dm.org/raszi/node-tmp)
[![npm version](https://badge.fury.io/js/tmp.svg)](https://badge.fury.io/js/tmp)
[![API documented](https://img.shields.io/badge/API-documented-brightgreen.svg)](https://raszi.github.io/node-tmp/)
[![Known Vulnerabilities](https://snyk.io/test/npm/tmp/badge.svg)](https://snyk.io/test/npm/tmp)
## About
This is a [widely used library][2] to create temporary files and directories
in a [node.js][1] environment.
Tmp offers both an asynchronous and a synchronous API. For all API calls, all
the parameters are optional. There also exists a promisified version of the
API, see (5) under references below.
Tmp uses crypto for determining random file names, or, when using templates,
a six letter random identifier. And just in case that you do not have that much
entropy left on your system, Tmp will fall back to pseudo random numbers.
You can set whether you want to remove the temporary file on process exit or
not, and the destination directory can also be set.
## How to install
```bash
npm install tmp
```
## Usage
Please also check [API docs][4].
### Asynchronous file creation
Simple temporary file creation, the file will be closed and unlinked on process exit.
```javascript
var tmp = require('tmp');
tmp.file(function _tempFileCreated(err, path, fd, cleanupCallback) {
if (err) throw err;
console.log('File: ', path);
console.log('Filedescriptor: ', fd);
// If we don't need the file anymore we could manually call the cleanupCallback
// But that is not necessary if we didn't pass the keep option because the library
// will clean after itself.
cleanupCallback();
});
```
### Synchronous file creation
A synchronous version of the above.
```javascript
var tmp = require('tmp');
var tmpobj = tmp.fileSync();
console.log('File: ', tmpobj.name);
console.log('Filedescriptor: ', tmpobj.fd);
// If we don't need the file anymore we could manually call the removeCallback
// But that is not necessary if we didn't pass the keep option because the library
// will clean after itself.
tmpobj.removeCallback();
```
Note that this might throw an exception if either the maximum limit of retries
for creating a temporary name fails, or, in case that you do not have the permission
to write to the directory where the temporary file should be created in.
### Asynchronous directory creation
Simple temporary directory creation, it will be removed on process exit.
If the directory still contains items on process exit, then it won't be removed.
```javascript
var tmp = require('tmp');
tmp.dir(function _tempDirCreated(err, path, cleanupCallback) {
if (err) throw err;
console.log('Dir: ', path);
// Manual cleanup
cleanupCallback();
});
```
If you want to cleanup the directory even when there are entries in it, then
you can pass the `unsafeCleanup` option when creating it.
### Synchronous directory creation
A synchronous version of the above.
```javascript
var tmp = require('tmp');
var tmpobj = tmp.dirSync();
console.log('Dir: ', tmpobj.name);
// Manual cleanup
tmpobj.removeCallback();
```
Note that this might throw an exception if either the maximum limit of retries
for creating a temporary name fails, or, in case that you do not have the permission
to write to the directory where the temporary directory should be created in.
### Asynchronous filename generation
It is possible with this library to generate a unique filename in the specified
directory.
```javascript
var tmp = require('tmp');
tmp.tmpName(function _tempNameGenerated(err, path) {
if (err) throw err;
console.log('Created temporary filename: ', path);
});
```
### Synchronous filename generation
A synchronous version of the above.
```javascript
var tmp = require('tmp');
var name = tmp.tmpNameSync();
console.log('Created temporary filename: ', name);
```
## Advanced usage
### Asynchronous file creation
Creates a file with mode `0644`, prefix will be `prefix-` and postfix will be `.txt`.
```javascript
var tmp = require('tmp');
tmp.file({ mode: 0644, prefix: 'prefix-', postfix: '.txt' }, function _tempFileCreated(err, path, fd) {
if (err) throw err;
console.log('File: ', path);
console.log('Filedescriptor: ', fd);
});
```
### Synchronous file creation
A synchronous version of the above.
```javascript
var tmp = require('tmp');
var tmpobj = tmp.fileSync({ mode: 0644, prefix: 'prefix-', postfix: '.txt' });
console.log('File: ', tmpobj.name);
console.log('Filedescriptor: ', tmpobj.fd);
```
### Controlling the Descriptor
As a side effect of creating a unique file `tmp` gets a file descriptor that is
returned to the user as the `fd` parameter. The descriptor may be used by the
application and is closed when the `removeCallback` is invoked.
In some use cases the application does not need the descriptor, needs to close it
without removing the file, or needs to remove the file without closing the
descriptor. Two options control how the descriptor is managed:
* `discardDescriptor` - if `true` causes `tmp` to close the descriptor after the file
is created. In this case the `fd` parameter is undefined.
* `detachDescriptor` - if `true` causes `tmp` to return the descriptor in the `fd`
parameter, but it is the application's responsibility to close it when it is no
longer needed.
```javascript
var tmp = require('tmp');
tmp.file({ discardDescriptor: true }, function _tempFileCreated(err, path, fd, cleanupCallback) {
if (err) throw err;
// fd will be undefined, allowing application to use fs.createReadStream(path)
// without holding an unused descriptor open.
});
```
```javascript
var tmp = require('tmp');
tmp.file({ detachDescriptor: true }, function _tempFileCreated(err, path, fd, cleanupCallback) {
if (err) throw err;
cleanupCallback();
// Application can store data through fd here; the space used will automatically
// be reclaimed by the operating system when the descriptor is closed or program
// terminates.
});
```
### Asynchronous directory creation
Creates a directory with mode `0755`, prefix will be `myTmpDir_`.
```javascript
var tmp = require('tmp');
tmp.dir({ mode: 0750, prefix: 'myTmpDir_' }, function _tempDirCreated(err, path) {
if (err) throw err;
console.log('Dir: ', path);
});
```
### Synchronous directory creation
Again, a synchronous version of the above.
```javascript
var tmp = require('tmp');
var tmpobj = tmp.dirSync({ mode: 0750, prefix: 'myTmpDir_' });
console.log('Dir: ', tmpobj.name);
```
### mkstemp like, asynchronously
Creates a new temporary directory with mode `0700` and filename like `/tmp/tmp-nk2J1u`.
```javascript
var tmp = require('tmp');
tmp.dir({ template: '/tmp/tmp-XXXXXX' }, function _tempDirCreated(err, path) {
if (err) throw err;
console.log('Dir: ', path);
});
```
### mkstemp like, synchronously
This will behave similarly to the asynchronous version.
```javascript
var tmp = require('tmp');
var tmpobj = tmp.dirSync({ template: '/tmp/tmp-XXXXXX' });
console.log('Dir: ', tmpobj.name);
```
### Asynchronous filename generation
The `tmpName()` function accepts the `prefix`, `postfix`, `dir`, etc. parameters also:
```javascript
var tmp = require('tmp');
tmp.tmpName({ template: '/tmp/tmp-XXXXXX' }, function _tempNameGenerated(err, path) {
if (err) throw err;
console.log('Created temporary filename: ', path);
});
```
### Synchronous filename generation
The `tmpNameSync()` function works similarly to `tmpName()`.
```javascript
var tmp = require('tmp');
var tmpname = tmp.tmpNameSync({ template: '/tmp/tmp-XXXXXX' });
console.log('Created temporary filename: ', tmpname);
```
## Graceful cleanup
One may want to cleanup the temporary files even when an uncaught exception
occurs. To enforce this, you can call the `setGracefulCleanup()` method:
```javascript
var tmp = require('tmp');
tmp.setGracefulCleanup();
```
## Options
All options are optional :)
* `mode`: the file mode to create with, it fallbacks to `0600` on file creation and `0700` on directory creation
* `prefix`: the optional prefix, fallbacks to `tmp-` if not provided
* `postfix`: the optional postfix, fallbacks to `.tmp` on file creation
* `template`: [`mkstemp`][3] like filename template, no default
* `dir`: the optional temporary directory, fallbacks to system default (guesses from environment)
* `tries`: how many times should the function try to get a unique filename before giving up, default `3`
* `keep`: signals that the temporary file or directory should not be deleted on exit, default is `false`, means delete
* Please keep in mind that it is recommended in this case to call the provided `cleanupCallback` function manually.
* `unsafeCleanup`: recursively removes the created temporary directory, even when it's not empty. default is `false`
[1]: http://nodejs.org/
[2]: https://www.npmjs.com/browse/depended/tmp
[3]: http://www.kernel.org/doc/man-pages/online/pages/man3/mkstemp.3.html
[4]: https://raszi.github.io/node-tmp/
[5]: https://github.com/benjamingr/tmp-promise

611
tools/node_modules/eslint/node_modules/tmp/lib/tmp.js generated vendored Normal file
View File

@ -0,0 +1,611 @@
/*!
* Tmp
*
* Copyright (c) 2011-2017 KARASZI Istvan <github@spam.raszi.hu>
*
* MIT Licensed
*/
/*
* Module dependencies.
*/
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const osTmpDir = require('os-tmpdir');
const _c = process.binding('constants');
/*
* The working inner variables.
*/
const
/**
* The temporary directory.
* @type {string}
*/
tmpDir = osTmpDir(),
// the random characters to choose from
RANDOM_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
TEMPLATE_PATTERN = /XXXXXX/,
DEFAULT_TRIES = 3,
CREATE_FLAGS = (_c.O_CREAT || _c.fs.O_CREAT) | (_c.O_EXCL || _c.fs.O_EXCL) | (_c.O_RDWR || _c.fs.O_RDWR),
EBADF = _c.EBADF || _c.os.errno.EBADF,
ENOENT = _c.ENOENT || _c.os.errno.ENOENT,
DIR_MODE = 448 /* 0o700 */,
FILE_MODE = 384 /* 0o600 */,
// this will hold the objects need to be removed on exit
_removeObjects = [];
var
_gracefulCleanup = false,
_uncaughtException = false;
/**
* Random name generator based on crypto.
* Adapted from http://blog.tompawlak.org/how-to-generate-random-values-nodejs-javascript
*
* @param {number} howMany
* @returns {string} the generated random name
* @private
*/
function _randomChars(howMany) {
var
value = [],
rnd = null;
// make sure that we do not fail because we ran out of entropy
try {
rnd = crypto.randomBytes(howMany);
} catch (e) {
rnd = crypto.pseudoRandomBytes(howMany);
}
for (var i = 0; i < howMany; i++) {
value.push(RANDOM_CHARS[rnd[i] % RANDOM_CHARS.length]);
}
return value.join('');
}
/**
* Checks whether the `obj` parameter is defined or not.
*
* @param {Object} obj
* @returns {boolean} true if the object is undefined
* @private
*/
function _isUndefined(obj) {
return typeof obj === 'undefined';
}
/**
* Parses the function arguments.
*
* This function helps to have optional arguments.
*
* @param {(Options|Function)} options
* @param {Function} callback
* @returns {Array} parsed arguments
* @private
*/
function _parseArguments(options, callback) {
if (typeof options == 'function') {
return [callback || {}, options];
}
if (_isUndefined(options)) {
return [{}, callback];
}
return [options, callback];
}
/**
* Generates a new temporary name.
*
* @param {Object} opts
* @returns {string} the new random name according to opts
* @private
*/
function _generateTmpName(opts) {
if (opts.name) {
return path.join(opts.dir || tmpDir, opts.name);
}
// mkstemps like template
if (opts.template) {
return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
}
// prefix and postfix
const name = [
opts.prefix || 'tmp-',
process.pid,
_randomChars(12),
opts.postfix || ''
].join('');
return path.join(opts.dir || tmpDir, name);
}
/**
* Gets a temporary file name.
*
* @param {(Options|tmpNameCallback)} options options or callback
* @param {?tmpNameCallback} callback the callback function
*/
function tmpName(options, callback) {
var
args = _parseArguments(options, callback),
opts = args[0],
cb = args[1],
tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
if (isNaN(tries) || tries < 0)
return cb(new Error('Invalid tries'));
if (opts.template && !opts.template.match(TEMPLATE_PATTERN))
return cb(new Error('Invalid template provided'));
(function _getUniqueName() {
const name = _generateTmpName(opts);
// check whether the path exists then retry if needed
fs.stat(name, function (err) {
if (!err) {
if (tries-- > 0) return _getUniqueName();
return cb(new Error('Could not get a unique tmp filename, max tries reached ' + name));
}
cb(null, name);
});
}());
}
/**
* Synchronous version of tmpName.
*
* @param {Object} options
* @returns {string} the generated random name
* @throws {Error} if the options are invalid or could not generate a filename
*/
function tmpNameSync(options) {
var
args = _parseArguments(options),
opts = args[0],
tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
if (isNaN(tries) || tries < 0)
throw new Error('Invalid tries');
if (opts.template && !opts.template.match(TEMPLATE_PATTERN))
throw new Error('Invalid template provided');
do {
const name = _generateTmpName(opts);
try {
fs.statSync(name);
} catch (e) {
return name;
}
} while (tries-- > 0);
throw new Error('Could not get a unique tmp filename, max tries reached');
}
/**
* Creates and opens a temporary file.
*
* @param {(Options|fileCallback)} options the config options or the callback function
* @param {?fileCallback} callback
*/
function file(options, callback) {
var
args = _parseArguments(options, callback),
opts = args[0],
cb = args[1];
opts.postfix = (_isUndefined(opts.postfix)) ? '.tmp' : opts.postfix;
// gets a temporary filename
tmpName(opts, function _tmpNameCreated(err, name) {
if (err) return cb(err);
// create and open the file
fs.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err, fd) {
if (err) return cb(err);
if (opts.discardDescriptor) {
return fs.close(fd, function _discardCallback(err) {
if (err) {
// Low probability, and the file exists, so this could be
// ignored. If it isn't we certainly need to unlink the
// file, and if that fails too its error is more
// important.
try {
fs.unlinkSync(name);
} catch (e) {
if (!isENOENT(e)) {
err = e;
}
}
return cb(err);
}
cb(null, name, undefined, _prepareTmpFileRemoveCallback(name, -1, opts));
});
}
if (opts.detachDescriptor) {
return cb(null, name, fd, _prepareTmpFileRemoveCallback(name, -1, opts));
}
cb(null, name, fd, _prepareTmpFileRemoveCallback(name, fd, opts));
});
});
}
/**
* Synchronous version of file.
*
* @param {Options} options
* @returns {FileSyncObject} object consists of name, fd and removeCallback
* @throws {Error} if cannot create a file
*/
function fileSync(options) {
var
args = _parseArguments(options),
opts = args[0];
opts.postfix = opts.postfix || '.tmp';
const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
const name = tmpNameSync(opts);
var fd = fs.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
if (opts.discardDescriptor) {
fs.closeSync(fd);
fd = undefined;
}
return {
name: name,
fd: fd,
removeCallback: _prepareTmpFileRemoveCallback(name, discardOrDetachDescriptor ? -1 : fd, opts)
};
}
/**
* Removes files and folders in a directory recursively.
*
* @param {string} root
* @private
*/
function _rmdirRecursiveSync(root) {
const dirs = [root];
do {
var
dir = dirs.pop(),
deferred = false,
files = fs.readdirSync(dir);
for (var i = 0, length = files.length; i < length; i++) {
var
file = path.join(dir, files[i]),
stat = fs.lstatSync(file); // lstat so we don't recurse into symlinked directories
if (stat.isDirectory()) {
if (!deferred) {
deferred = true;
dirs.push(dir);
}
dirs.push(file);
} else {
fs.unlinkSync(file);
}
}
if (!deferred) {
fs.rmdirSync(dir);
}
} while (dirs.length !== 0);
}
/**
* Creates a temporary directory.
*
* @param {(Options|dirCallback)} options the options or the callback function
* @param {?dirCallback} callback
*/
function dir(options, callback) {
var
args = _parseArguments(options, callback),
opts = args[0],
cb = args[1];
// gets a temporary filename
tmpName(opts, function _tmpNameCreated(err, name) {
if (err) return cb(err);
// create the directory
fs.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err) {
if (err) return cb(err);
cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
});
});
}
/**
* Synchronous version of dir.
*
* @param {Options} options
* @returns {DirSyncObject} object consists of name and removeCallback
* @throws {Error} if it cannot create a directory
*/
function dirSync(options) {
var
args = _parseArguments(options),
opts = args[0];
const name = tmpNameSync(opts);
fs.mkdirSync(name, opts.mode || DIR_MODE);
return {
name: name,
removeCallback: _prepareTmpDirRemoveCallback(name, opts)
};
}
/**
* Prepares the callback for removal of the temporary file.
*
* @param {string} name the path of the file
* @param {number} fd file descriptor
* @param {Object} opts
* @returns {fileCallback}
* @private
*/
function _prepareTmpFileRemoveCallback(name, fd, opts) {
const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
try {
if (0 <= fdPath[0]) {
fs.closeSync(fdPath[0]);
}
}
catch (e) {
// under some node/windows related circumstances, a temporary file
// may have not be created as expected or the file was already closed
// by the user, in which case we will simply ignore the error
if (!isEBADF(e) && !isENOENT(e)) {
// reraise any unanticipated error
throw e;
}
}
try {
fs.unlinkSync(fdPath[1]);
}
catch (e) {
if (!isENOENT(e)) {
// reraise any unanticipated error
throw e;
}
}
}, [fd, name]);
if (!opts.keep) {
_removeObjects.unshift(removeCallback);
}
return removeCallback;
}
/**
* Prepares the callback for removal of the temporary directory.
*
* @param {string} name
* @param {Object} opts
* @returns {Function} the callback
* @private
*/
function _prepareTmpDirRemoveCallback(name, opts) {
const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs.rmdirSync.bind(fs);
const removeCallback = _prepareRemoveCallback(removeFunction, name);
if (!opts.keep) {
_removeObjects.unshift(removeCallback);
}
return removeCallback;
}
/**
* Creates a guarded function wrapping the removeFunction call.
*
* @param {Function} removeFunction
* @param {Object} arg
* @returns {Function}
* @private
*/
function _prepareRemoveCallback(removeFunction, arg) {
var called = false;
return function _cleanupCallback(next) {
if (!called) {
const index = _removeObjects.indexOf(_cleanupCallback);
if (index >= 0) {
_removeObjects.splice(index, 1);
}
called = true;
removeFunction(arg);
}
if (next) next(null);
};
}
/**
* The garbage collector.
*
* @private
*/
function _garbageCollector() {
if (_uncaughtException && !_gracefulCleanup) {
return;
}
// the function being called removes itself from _removeObjects,
// loop until _removeObjects is empty
while (_removeObjects.length) {
try {
_removeObjects[0].call(null);
} catch (e) {
// already removed?
}
}
}
/**
* Helper for testing against EBADF to compensate changes made to Node 7.x under Windows.
*/
function isEBADF(error) {
return isExpectedError(error, -EBADF, 'EBADF');
}
/**
* Helper for testing against ENOENT to compensate changes made to Node 7.x under Windows.
*/
function isENOENT(error) {
return isExpectedError(error, -ENOENT, 'ENOENT');
}
/**
* Helper to determine whether the expected error code matches the actual code and errno,
* which will differ between the supported node versions.
*
* - Node >= 7.0:
* error.code {String}
* error.errno {String|Number} any numerical value will be negated
*
* - Node >= 6.0 < 7.0:
* error.code {String}
* error.errno {Number} negated
*
* - Node >= 4.0 < 6.0: introduces SystemError
* error.code {String}
* error.errno {Number} negated
*
* - Node >= 0.10 < 4.0:
* error.code {Number} negated
* error.errno n/a
*/
function isExpectedError(error, code, errno) {
return error.code == code || error.code == errno;
}
/**
* Sets the graceful cleanup.
*
* Also removes the created files and directories when an uncaught exception occurs.
*/
function setGracefulCleanup() {
_gracefulCleanup = true;
}
const version = process.versions.node.split('.').map(function (value) {
return parseInt(value, 10);
});
if (version[0] === 0 && (version[1] < 9 || version[1] === 9 && version[2] < 5)) {
process.addListener('uncaughtException', function _uncaughtExceptionThrown(err) {
_uncaughtException = true;
_garbageCollector();
throw err;
});
}
process.addListener('exit', function _exit(code) {
if (code) _uncaughtException = true;
_garbageCollector();
});
/**
* Configuration options.
*
* @typedef {Object} Options
* @property {?number} tries the number of tries before give up the name generation
* @property {?string} template the "mkstemp" like filename template
* @property {?string} name fix name
* @property {?string} dir the tmp directory to use
* @property {?string} prefix prefix for the generated name
* @property {?string} postfix postfix for the generated name
*/
/**
* @typedef {Object} FileSyncObject
* @property {string} name the name of the file
* @property {string} fd the file descriptor
* @property {fileCallback} removeCallback the callback function to remove the file
*/
/**
* @typedef {Object} DirSyncObject
* @property {string} name the name of the directory
* @property {fileCallback} removeCallback the callback function to remove the directory
*/
/**
* @callback tmpNameCallback
* @param {?Error} err the error object if anything goes wrong
* @param {string} name the temporary file name
*/
/**
* @callback fileCallback
* @param {?Error} err the error object if anything goes wrong
* @param {string} name the temporary file name
* @param {number} fd the file descriptor
* @param {cleanupCallback} fn the cleanup callback function
*/
/**
* @callback dirCallback
* @param {?Error} err the error object if anything goes wrong
* @param {string} name the temporary file name
* @param {cleanupCallback} fn the cleanup callback function
*/
/**
* Removes the temporary created file or directory.
*
* @callback cleanupCallback
* @param {simpleCallback} [next] function to call after entry was removed
*/
/**
* Callback function for function composition.
* @see {@link https://github.com/raszi/node-tmp/issues/57|raszi/node-tmp#57}
*
* @callback simpleCallback
*/
// exporting all the needed methods
module.exports.tmpdir = tmpDir;
module.exports.dir = dir;
module.exports.dirSync = dirSync;
module.exports.file = file;
module.exports.fileSync = fileSync;
module.exports.tmpName = tmpName;
module.exports.tmpNameSync = tmpNameSync;
module.exports.setGracefulCleanup = setGracefulCleanup;

View File

@ -0,0 +1,47 @@
{
"author": {
"name": "KARASZI István",
"email": "github@spam.raszi.hu",
"url": "http://raszi.hu/"
},
"bugs": {
"url": "http://github.com/raszi/node-tmp/issues"
},
"bundleDependencies": false,
"dependencies": {
"os-tmpdir": "~1.0.2"
},
"deprecated": false,
"description": "Temporary file and directory creator",
"devDependencies": {
"vows": "~0.7.0"
},
"engines": {
"node": ">=0.6.0"
},
"files": [
"lib/"
],
"homepage": "http://github.com/raszi/node-tmp",
"keywords": [
"temporary",
"tmp",
"temp",
"tempdir",
"tempfile",
"tmpdir",
"tmpfile"
],
"license": "MIT",
"main": "lib/tmp.js",
"name": "tmp",
"repository": {
"type": "git",
"url": "git+https://github.com/raszi/node-tmp.git"
},
"scripts": {
"doc": "jsdoc -c .jsdoc.json",
"test": "vows test/*-test.js"
},
"version": "0.0.33"
}

View File

@ -105,13 +105,13 @@ For JSPM users:
{
"compilerOptions": {
"module": "system",
"importHelpers": true,
"baseUrl": "./",
"paths": {
"tslib" : ["jspm_packages/npm/tslib@1.9.3/tslib.d.ts"]
}
}
}
"importHelpers": true,
"baseUrl": "./",
"paths": {
"tslib" : ["jspm_packages/npm/tslib@1.10.0/tslib.d.ts"]
}
}
}
```

View File

@ -28,5 +28,5 @@
"url": "git+https://github.com/Microsoft/tslib.git"
},
"typings": "tslib.d.ts",
"version": "1.9.3"
"version": "1.10.0"
}

View File

@ -40,14 +40,16 @@ export var __assign = function() {
export function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
}
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
export function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@ -135,12 +137,20 @@ export function __read(o, n) {
export function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
export function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
return ar;
}
export function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
export function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
export function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");

View File

@ -22,12 +22,13 @@ var __metadata;
var __awaiter;
var __generator;
var __exportStar;
var __values;
var __read;
var __spread;
var __await;
var __asyncGenerator;
var __asyncDelegator;
var __values;
var __read;
var __spread;
var __spreadArrays;
var __await;
var __asyncGenerator;
var __asyncDelegator;
var __asyncValues;
var __makeTemplateObject;
var __importStar;
@ -76,14 +77,16 @@ var __importDefault;
__rest = function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
__decorate = function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@ -171,12 +174,20 @@ var __importDefault;
__spread = function () {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
};
__await = function (v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
};
return ar;
};
__spreadArrays = function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
__await = function (v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
};
__asyncGenerator = function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
@ -230,12 +241,13 @@ var __importDefault;
exporter("__awaiter", __awaiter);
exporter("__generator", __generator);
exporter("__exportStar", __exportStar);
exporter("__values", __values);
exporter("__read", __read);
exporter("__spread", __spread);
exporter("__await", __await);
exporter("__asyncGenerator", __asyncGenerator);
exporter("__asyncDelegator", __asyncDelegator);
exporter("__values", __values);
exporter("__read", __read);
exporter("__spread", __spread);
exporter("__spreadArrays", __spreadArrays);
exporter("__await", __await);
exporter("__asyncGenerator", __asyncGenerator);
exporter("__asyncDelegator", __asyncDelegator);
exporter("__asyncValues", __asyncValues);
exporter("__makeTemplateObject", __makeTemplateObject);
exporter("__importStar", __importStar);

View File

@ -0,0 +1,87 @@
'use strict'
module.exports = convert
function convert(test) {
if (typeof test === 'string') {
return typeFactory(test)
}
if (test === null || test === undefined) {
return ok
}
if (typeof test === 'object') {
return ('length' in test ? anyFactory : matchesFactory)(test)
}
if (typeof test === 'function') {
return test
}
throw new Error('Expected function, string, or object as test')
}
function convertAll(tests) {
var results = []
var length = tests.length
var index = -1
while (++index < length) {
results[index] = convert(tests[index])
}
return results
}
// Utility assert each property in `test` is represented in `node`, and each
// values are strictly equal.
function matchesFactory(test) {
return matches
function matches(node) {
var key
for (key in test) {
if (node[key] !== test[key]) {
return false
}
}
return true
}
}
function anyFactory(tests) {
var checks = convertAll(tests)
var length = checks.length
return matches
function matches() {
var index = -1
while (++index < length) {
if (checks[index].apply(this, arguments)) {
return true
}
}
return false
}
}
// Utility to convert a string into a function which checks a given nodes type
// for said string.
function typeFactory(test) {
return type
function type(node) {
return Boolean(node && node.type === test)
}
}
// Utility to return true.
function ok() {
return true
}

View File

@ -1,11 +1,15 @@
'use strict'
var convert = require('./convert')
module.exports = is
// Assert if `test` passes for `node`. When a `parent` node is known the
// `index` of node.
is.convert = convert
// Assert if `test` passes for `node`.
// When a `parent` node is known the `index` of node should also be given.
// eslint-disable-next-line max-params
function is(test, node, index, parent, context) {
function is(node, test, index, parent, context) {
var hasParent = parent !== null && parent !== undefined
var hasIndex = index !== null && index !== undefined
var check = convert(test)
@ -17,7 +21,7 @@ function is(test, node, index, parent, context) {
throw new Error('Expected positive finite index or child node')
}
if (hasParent && (!is(null, parent) || !parent.children)) {
if (hasParent && (!is(parent) || !parent.children)) {
throw new Error('Expected parent node')
}
@ -31,87 +35,3 @@ function is(test, node, index, parent, context) {
return Boolean(check.call(context, node, index, parent))
}
function convert(test) {
if (typeof test === 'string') {
return typeFactory(test)
}
if (test === null || test === undefined) {
return ok
}
if (typeof test === 'object') {
return ('length' in test ? anyFactory : matchesFactory)(test)
}
if (typeof test === 'function') {
return test
}
throw new Error('Expected function, string, or object as test')
}
function convertAll(tests) {
var results = []
var length = tests.length
var index = -1
while (++index < length) {
results[index] = convert(tests[index])
}
return results
}
// Utility assert each property in `test` is represented in `node`, and each
// values are strictly equal.
function matchesFactory(test) {
return matches
function matches(node) {
var key
for (key in test) {
if (node[key] !== test[key]) {
return false
}
}
return true
}
}
function anyFactory(tests) {
var checks = convertAll(tests)
var length = checks.length
return matches
function matches() {
var index = -1
while (++index < length) {
if (checks[index].apply(this, arguments)) {
return true
}
}
return false
}
}
// Utility to convert a string into a function which checks a given nodes type
// for said string.
function typeFactory(test) {
return type
function type(node) {
return Boolean(node && node.type === test)
}
}
// Utility to return true.
function ok() {
return true
}

View File

@ -5,7 +5,7 @@
"url": "https://wooorm.com"
},
"bugs": {
"url": "https://github.com/syntax-tree/hast-util-to-html/issues"
"url": "https://github.com/syntax-tree/unist-util-is/issues"
},
"bundleDependencies": false,
"contributors": [
@ -29,7 +29,8 @@
"xo": "^0.24.0"
},
"files": [
"index.js"
"index.js",
"convert.js"
],
"homepage": "https://github.com/syntax-tree/unist-util-is#readme",
"keywords": [
@ -76,7 +77,7 @@
"test-api": "node test",
"test-coverage": "nyc --reporter lcov tape test.js"
},
"version": "2.1.3",
"version": "3.0.0",
"xo": {
"prettier": true,
"esnext": false,

View File

@ -31,49 +31,49 @@ function test(node, n) {
}
is() // => false
is(null, {children: []}) // => false
is(null, node) // => true
is('strong', node) // => true
is('emphasis', node) // => false
is({children: []}) // => false
is(node) // => true
is(node, 'strong') // => true
is(node, 'emphasis') // => false
is(node, node) // => true
is({type: 'paragraph'}, parent) // => true
is({type: 'strong'}, parent) // => false
is(parent, {type: 'paragraph'}) // => true
is(parent, {type: 'strong'}) // => false
is(test, node) // => false
is(test, node, 4, parent) // => false
is(test, node, 5, parent) // => true
is(node, test) // => false
is(node, test, 4, parent) // => false
is(node, test, 5, parent) // => true
```
## API
### `is(test, node[, index, parent[, context]])`
### `is(node[, test[, index, parent[, context]]])`
###### Parameters
* `node` ([`Node`][node]) — Node to check.
* `test` ([`Function`][test], `string`, `Object`, or `Array.<Test>`, optional)
— When not given, checks if `node` is a [`Node`][node].
When `string`, works like passing `node => node.type === test`.
When `array`, checks if any one of the subtests pass.
When `object`, checks that all keys in `test` are in `node`,
and that they have strictly equal values
* `node` ([`Node`][node]) — Node to check. `false` is returned
* `index` (`number`, optional) — [Index][] of `node` in `parent`
* `parent` ([`Node`][node], optional) — [Parent][] of `node`
* `context` (`*`, optional) — Context object to invoke `test` with
###### Returns
`boolean` — Whether `test` passed *and* `node` is a [`Node`][node] (object
with `type` set to a non-empty `string`).
`boolean` — Whether `test` passed *and* `node` is a [`Node`][node] (object with
`type` set to a non-empty `string`).
#### `function test(node[, index, parent])`
###### Parameters
* `node` (`Node`) — Node to test
* `index` (`number?`) — Position of `node` in `parent`
* `parent` (`Node?`) — Parent of `node`
* `node` ([`Node`][node]) — Node to check
* `index` (`number?`) — [Index][] of `node` in `parent`
* `parent` ([`Node?`][node]) — [Parent][] of `node`
###### Context
@ -83,6 +83,41 @@ with `type` set to a non-empty `string`).
`boolean?` — Whether `node` matches.
### `is.convert(test)`
Create a test function from `test`, that can later be called with a `node`,
`index`, and `parent`.
Useful if youre going to test many nodes, for example when creating a utility
where something else passes an is-compatible test.
Can also be accessed with `require('unist-util-is/convert')`.
For example:
```js
var u = require('unist-builder')
var convert = require('unist-util-is/convert')
var test = convert('leaf')
var tree = u('tree', [
u('node', [u('leaf', '1')]),
u('leaf', '2'),
u('node', [u('leaf', '3'), u('leaf', '4')]),
u('leaf', '5')
])
var leafs = tree.children.filter((child, index) => test(child, index, tree))
console.log(leafs)
```
Yields:
```js
[({type: 'leaf', value: '2'}, {type: 'leaf', value: '5'})]
```
## Related
* [`unist-util-find-after`](https://github.com/syntax-tree/unist-util-find-after)

View File

@ -2,7 +2,7 @@
module.exports = visitParents
var is = require('unist-util-is')
var convert = require('unist-util-is/convert')
var CONTINUE = true
var SKIP = 'skip'
@ -13,12 +13,16 @@ visitParents.SKIP = SKIP
visitParents.EXIT = EXIT
function visitParents(tree, test, visitor, reverse) {
var is
if (typeof test === 'function' && typeof visitor !== 'function') {
reverse = visitor
visitor = test
test = null
}
is = convert(test)
one(tree, null, [])
// Visit a single node.
@ -26,7 +30,7 @@ function visitParents(tree, test, visitor, reverse) {
var result = []
var subresult
if (!test || is(test, node, index, parents[parents.length - 1] || null)) {
if (!test || is(node, index, parents[parents.length - 1] || null)) {
result = toResult(visitor(node, parents))
if (result[0] === EXIT) {

View File

@ -16,7 +16,7 @@
}
],
"dependencies": {
"unist-util-is": "^2.1.2"
"unist-util-is": "^3.0.0"
},
"deprecated": false,
"description": "Recursively walk over unist nodes, with ancestral information",
@ -75,7 +75,7 @@
"test-api": "node test",
"test-coverage": "nyc --reporter lcov tape test.js"
},
"version": "2.1.1",
"version": "2.1.2",
"xo": {
"prettier": true,
"esnext": false,

View File

@ -20,14 +20,14 @@
"description": "Convert between positions (line and column-based) and offsets (range-based) locations in a virtual file",
"devDependencies": {
"browserify": "^16.0.0",
"nyc": "^13.0.0",
"prettier": "^1.12.1",
"nyc": "^14.0.0",
"prettier": "^1.0.0",
"remark-cli": "^6.0.0",
"remark-preset-wooorm": "^4.0.0",
"remark-preset-wooorm": "^5.0.0",
"tape": "^4.0.0",
"tinyify": "^2.4.3",
"vfile": "^3.0.0",
"xo": "^0.23.0"
"tinyify": "^2.0.0",
"vfile": "^4.0.0",
"xo": "^0.24.0"
},
"files": [
"index.js"
@ -69,20 +69,15 @@
"build": "npm run build-bundle && npm run build-mangle",
"build-bundle": "browserify . -s vfileLocation > vfile-location.js",
"build-mangle": "browserify . -s vfileLocation -p tinyify > vfile-location.min.js",
"format": "remark . -qfo && prettier --write '**/*.js' && xo --fix",
"format": "remark . -qfo && prettier --write \"**/*.js\" && xo --fix",
"test": "npm run format && npm run build && npm run test-coverage",
"test-api": "node test",
"test-coverage": "nyc --reporter lcov tape test.js"
},
"version": "2.0.4",
"version": "2.0.5",
"xo": {
"prettier": true,
"esnext": false,
"rules": {
"no-var": "off",
"prefer-arrow-callback": "off",
"object-shorthand": "off"
},
"ignores": [
"vfile-location.js"
]

View File

@ -3,16 +3,19 @@
[![Build][build-badge]][build]
[![Coverage][coverage-badge]][coverage]
[![Downloads][downloads-badge]][downloads]
[![Size][size-badge]][size]
[![Sponsors][sponsors-badge]][collective]
[![Backers][backers-badge]][collective]
[![Chat][chat-badge]][chat]
Convert between positions (line and column-based) and offsets
(range-based) locations in a [virtual file][vfile].
Convert between positions (line and column-based) and offsets (range-based)
locations in a [virtual file][vfile].
## Installation
## Install
[npm][]:
```bash
```sh
npm install vfile-location
```
@ -32,29 +35,30 @@ location.toPosition(offset) // => {line: 3, column: 3, offset: 10}
### `location = vfileLocation(doc)`
Get transform functions for the given `doc` (`string`) or
[`file`][vfile].
Get transform functions for the given `doc` (`string`) or [`file`][vfile].
Returns an object with [`toOffset`][to-offset] and
[`toPosition`][to-position].
Returns an object with [`toOffset`][to-offset] and [`toPosition`][to-position].
### `location.toOffset(position)`
Get the `offset` (`number`) for a line and column-based
[`position`][position] in the bound file. Returns `-1`
when given invalid or out of bounds input.
Get the `offset` (`number`) for a line and column-based [`position`][position]
in the bound file.
Returns `-1` when given invalid or out of bounds input.
### `location.toPosition(offset)`
Get the line and column-based [`position`][position] for `offset` in
the bound file.
Get the line and column-based [`position`][position] for `offset` in the bound
file.
## Contribute
See [`contributing.md` in `vfile/vfile`][contributing] for ways to get started.
See [`contributing.md`][contributing] in [`vfile/.github`][health] for ways to
get started.
See [`support.md`][support] for ways to get help.
This organisation has a [Code of Conduct][coc]. By interacting with this
repository, organisation, or community you agree to abide by its terms.
This project has a [Code of Conduct][coc].
By interacting with this repository, organisation, or community you agree to
abide by its terms.
## License
@ -74,12 +78,30 @@ repository, organisation, or community you agree to abide by its terms.
[downloads]: https://www.npmjs.com/package/vfile-location
[size-badge]: https://img.shields.io/bundlephobia/minzip/vfile-location.svg
[size]: https://bundlephobia.com/result?p=vfile-location
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
[backers-badge]: https://opencollective.com/unified/backers/badge.svg
[collective]: https://opencollective.com/unified
[chat-badge]: https://img.shields.io/badge/join%20the%20community-on%20spectrum-7b16ff.svg
[chat]: https://spectrum.chat/unified/vfile
[npm]: https://docs.npmjs.com/cli/install
[contributing]: https://github.com/vfile/.github/blob/master/contributing.md
[support]: https://github.com/vfile/.github/blob/master/support.md
[health]: https://github.com/vfile/.github
[coc]: https://github.com/vfile/.github/blob/master/code-of-conduct.md
[license]: license
[author]: https://wooorm.com
@ -91,7 +113,3 @@ repository, organisation, or community you agree to abide by its terms.
[to-position]: #locationtopositionoffset
[position]: https://github.com/syntax-tree/unist#position
[contributing]: https://github.com/vfile/vfile/blob/master/contributing.md
[coc]: https://github.com/vfile/vfile/blob/master/code-of-conduct.md

View File

@ -21,7 +21,7 @@
"eslint-scope": "^4.0.3",
"eslint-utils": "^1.3.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^6.0.0-alpha.0",
"espree": "^6.0.0",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
@ -53,16 +53,13 @@
"description": "An AST-based pattern checker for JavaScript.",
"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/polyfill": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"acorn": "^6.1.1",
"babel-loader": "^8.0.5",
"beefy": "^2.1.8",
"brfs": "^2.0.2",
"chai": "^4.0.1",
"cheerio": "^0.22.0",
"common-tags": "^1.8.0",
"coveralls": "^3.0.3",
"core-js": "^3.1.3",
"dateformat": "^3.0.3",
"ejs": "^2.6.1",
"eslint": "file:.",
@ -87,15 +84,16 @@
"markdownlint-cli": "^0.15.0",
"metro-memory-fs": "^0.53.1",
"mocha": "^6.1.2",
"mocha-junit-reporter": "^1.23.0",
"npm-license": "^0.3.3",
"nyc": "^13.3.0",
"proxyquire": "^2.0.1",
"puppeteer": "^1.14.0",
"recast": "^0.17.6",
"regenerator-runtime": "^0.13.2",
"shelljs": "^0.8.2",
"sinon": "^3.3.0",
"sinon": "^7.3.2",
"temp": "^0.9.0",
"through": "^2.3.8",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
"yorkie": "^2.0.0"
@ -137,7 +135,6 @@
"url": "git+https://github.com/eslint/eslint.git"
},
"scripts": {
"coveralls": "cat ./coverage/lcov.info | coveralls",
"docs": "node Makefile.js docs",
"fuzz": "node Makefile.js fuzz",
"generate-alpharelease": "node Makefile.js generatePrerelease -- alpha",
@ -147,10 +144,9 @@
"gensite": "node Makefile.js gensite",
"lint": "node Makefile.js lint",
"perf": "node Makefile.js perf",
"profile": "beefy tests/bench/bench.js --open -- -t brfs -t ./tests/bench/xform-rules.js -r espree",
"publish-release": "node Makefile.js publishRelease",
"test": "node Makefile.js test",
"webpack": "node Makefile.js webpack"
},
"version": "6.0.0-alpha.2"
"version": "6.0.1"
}

View File

@ -13,7 +13,7 @@ mkdir eslint-tmp
cd eslint-tmp
npm init --yes
npm install --global-style --no-bin-links --production --no-package-lock eslint@next
npm install --global-style --no-bin-links --production --no-package-lock eslint@latest
cd node_modules/eslint
npm install --no-bin-links --production --no-package-lock eslint-plugin-markdown@latest