Socket
Socket
Sign inDemoInstall

eslint-plugin-unicorn

Package Overview
Dependencies
Maintainers
1
Versions
106
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-unicorn - npm Package Compare versions

Comparing version 10.0.0 to 11.0.0

rules/consistent-function-scoping.js

8

index.js

@@ -13,3 +13,3 @@ 'use strict';

parserOptions: {
ecmaVersion: 2019,
ecmaVersion: 2020,
sourceType: 'module'

@@ -22,5 +22,7 @@ },

'unicorn/catch-error-name': 'error',
'unicorn/consistent-function-scoping': 'error',
'unicorn/custom-error-definition': 'off',
'unicorn/error-message': 'error',
'unicorn/escape-case': 'error',
'unicorn/expiring-todo-comments': 'error',
'unicorn/explicit-length-check': 'error',

@@ -37,2 +39,4 @@ 'unicorn/filename-case': 'error',

'unicorn/no-keyword-prefix': 'off',
'no-nested-ternary': 'off',
'unicorn/no-nested-ternary': 'error',
'unicorn/no-new-buffer': 'error',

@@ -46,2 +50,3 @@ 'unicorn/no-process-exit': 'error',

'unicorn/prefer-add-event-listener': 'error',
'unicorn/prefer-dataset': 'error',
'unicorn/prefer-event-key': 'error',

@@ -54,2 +59,3 @@ 'unicorn/prefer-exponentiation-operator': 'error',

'unicorn/prefer-query-selector': 'error',
'unicorn/prefer-reflect-apply': 'error',
'unicorn/prefer-spread': 'error',

@@ -56,0 +62,0 @@ 'unicorn/prefer-starts-ends-with': 'error',

25

package.json
{
"name": "eslint-plugin-unicorn",
"version": "10.0.0",
"version": "11.0.0",
"description": "Various awesome ESLint rules",

@@ -34,2 +34,3 @@ "license": "MIT",

"dependencies": {
"ci-info": "^2.0.0",
"clean-regexp": "^1.0.0",

@@ -39,3 +40,3 @@ "eslint-ast-utils": "^1.1.0",

"lodash.camelcase": "^4.3.0",
"lodash.defaultsdeep": "^4.6.0",
"lodash.defaultsdeep": "^4.6.1",
"lodash.kebabcase": "^4.1.1",

@@ -45,16 +46,18 @@ "lodash.snakecase": "^4.1.1",

"lodash.upperfirst": "^4.3.1",
"regexpp": "^2.0.1",
"regexpp": "^3.0.0",
"read-pkg": "^5.2.0",
"reserved-words": "^0.1.2",
"safe-regex": "^2.0.2"
"safe-regex": "^2.0.2",
"semver": "^6.3.0"
},
"devDependencies": {
"ava": "^2.1.0",
"babel-eslint": "^10.0.2",
"ava": "^2.3.0",
"babel-eslint": "^10.0.3",
"chalk": "^2.4.2",
"coveralls": "^3.0.4",
"del": "^5.0.0",
"eslint": "^6.0.1",
"coveralls": "^3.0.6",
"del": "^5.1.0",
"eslint": "^6.3.0",
"eslint-ava-rule-tester": "^3.0.0",
"eslint-plugin-eslint-plugin": "2.1.0",
"execa": "^2.0.3",
"execa": "^2.0.4",
"listr": "^0.14.3",

@@ -68,3 +71,3 @@ "nyc": "^14.1.1",

"peerDependencies": {
"eslint": ">=6.0.0"
"eslint": ">=6.3.0"
},

@@ -71,0 +74,0 @@ "ava": {

@@ -31,3 +31,3 @@ # eslint-plugin-unicorn [![Build Status](https://travis-ci.org/sindresorhus/eslint-plugin-unicorn.svg?branch=master)](https://travis-ci.org/sindresorhus/eslint-plugin-unicorn) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/eslint-plugin-unicorn/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/eslint-plugin-unicorn?branch=master)

"parserOptions": {
"ecmaVersion": 2019,
"ecmaVersion": 2020,
"sourceType": "module"

@@ -40,5 +40,7 @@ },

"unicorn/catch-error-name": "error",
"unicorn/consistent-function-scoping": "error",
"unicorn/custom-error-definition": "off",
"unicorn/error-message": "error",
"unicorn/escape-case": "error",
"unicorn/expiring-todo-comments": "error",
"unicorn/explicit-length-check": "error",

@@ -55,2 +57,4 @@ "unicorn/filename-case": "error",

"unicorn/no-keyword-prefix": "off",
"no-nested-ternary": "off",
"unicorn/no-nested-ternary": "error",
"unicorn/no-new-buffer": "error",

@@ -64,2 +68,3 @@ "unicorn/no-process-exit": "error",

"unicorn/prefer-add-event-listener": "error",
"unicorn/prefer-dataset": "error",
"unicorn/prefer-event-key": "error",

@@ -72,2 +77,3 @@ "unicorn/prefer-exponentiation-operator": "error",

"unicorn/prefer-query-selector": "error",
"unicorn/prefer-reflect-apply": "error",
"unicorn/prefer-spread": "error",

@@ -89,9 +95,11 @@ "unicorn/prefer-starts-ends-with": "error",

- [catch-error-name](docs/rules/catch-error-name.md) - Enforce a specific parameter name in catch clauses.
- [consistent-function-scoping](docs/rules/consistent-function-scoping.md) - Move function definitions to the highest possible scope.
- [custom-error-definition](docs/rules/custom-error-definition.md) - Enforce correct `Error` subclassing. *(fixable)*
- [error-message](docs/rules/error-message.md) - Enforce passing a `message` value when throwing a built-in error.
- [escape-case](docs/rules/escape-case.md) - Require escape sequences to use uppercase values. *(fixable)*
- [expiring-todo-comments](docs/rules/expiring-todo-comments.md) - Add expiration conditions to TODO comments.
- [explicit-length-check](docs/rules/explicit-length-check.md) - Enforce explicitly comparing the `length` property of a value. *(partly fixable)*
- [filename-case](docs/rules/filename-case.md) - Enforce a case style for filenames.
- [import-index](docs/rules/import-index.md) - Enforce importing index files with `.`. *(fixable)*
- [new-for-builtins](docs/rules/new-for-builtins.md) - Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean` and `Symbol`. *(fixable)*
- [new-for-builtins](docs/rules/new-for-builtins.md) - Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean`, `Symbol` and `BigInt`. *(fixable)*
- [no-abusive-eslint-disable](docs/rules/no-abusive-eslint-disable.md) - Enforce specifying rules to disable in `eslint-disable` comments.

@@ -104,2 +112,3 @@ - [no-array-instanceof](docs/rules/no-array-instanceof.md) - Require `Array.isArray()` instead of `instanceof Array`. *(fixable)*

- [no-keyword-prefix](docs/rules/no-keyword-prefix.md) - Disallow identifiers starting with `new` or `class`.
- [no-nested-ternary](docs/rules/no-nested-ternary.md) - Disallow nested ternary expressions. *(partly fixable)*
- [no-new-buffer](docs/rules/no-new-buffer.md) - Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. *(fixable)*

@@ -113,2 +122,3 @@ - [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`.

- [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) - Prefer `.addEventListener()` and `.removeEventListener()` over `on`-functions. *(partly fixable)*
- [prefer-dataset](docs/rules/prefer-dataset.md) - Prefer using `.dataset` on DOM elements over `.setAttribute(…)`. *(fixable)*
- [prefer-event-key](docs/rules/prefer-event-key.md) - Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. *(partly fixable)*

@@ -121,2 +131,3 @@ - [prefer-exponentiation-operator](docs/rules/prefer-exponentiation-operator.md) - Prefer the exponentiation operator over `Math.pow()` *(fixable)*

- [prefer-query-selector](docs/rules/prefer-query-selector.md) - Prefer `.querySelector()` over `.getElementById()`, `.querySelectorAll()` over `.getElementsByClassName()` and `.getElementsByTagName()`. *(partly fixable)*
- [prefer-reflect-apply](docs/rules/prefer-reflect-apply.md) - Prefer `Reflect.apply()` over `Function#apply()`. *(fixable)*
- [prefer-spread](docs/rules/prefer-spread.md) - Prefer the spread operator over `Array.from()`. *(fixable)*

@@ -154,5 +165,5 @@ - [prefer-starts-ends-with](docs/rules/prefer-starts-ends-with.md) - Prefer `String#startsWith()` & `String#endsWith()` over more complex alternatives.

- [Sindre Sorhus](https://github.com/sindresorhus)
- [Adam Babcock](https://github.com/MrHen)
- [futpib](https://github.com/futpib)
- [Sam Verschueren](https://github.com/SamVerschueren)
- [futpib](https://github.com/futpib)
- [Adam Babcock](https://github.com/MrHen)

@@ -162,6 +173,1 @@ ###### Former

- [Jeroen Engels](https://github.com/jfmengels)
## License
MIT

@@ -68,6 +68,11 @@ 'use strict';

const scope = scopeManager.acquire(scopeNode);
const variable = scope.set.get(node.name);
for (const reference of variable.references) {
fixings.push(fixer.replaceText(reference.identifier, expectedName));
const variables = scopeManager.getDeclaredVariables(scopeNode);
for (const variable of variables) {
if (variable.name !== node.name) {
continue;
}
for (const reference of variable.references) {
fixings.push(fixer.replaceText(reference.identifier, expectedName));
}
}

@@ -74,0 +79,0 @@

@@ -117,3 +117,3 @@ 'use strict';

if (filenameWithExtension === '<input>') {
if (filenameWithExtension === '<input>' || filenameWithExtension === '<text>') {
return {};

@@ -120,0 +120,0 @@ }

@@ -8,2 +8,4 @@ 'use strict';

'ArrayBuffer',
'BigInt64Array',
'BigUint64Array',
'DataView',

@@ -10,0 +12,0 @@ 'Date',

'use strict';
const getDocsUrl = require('./utils/get-docs-url');
const quoteString = require('./utils/quote-string');

@@ -57,3 +58,3 @@ const keys = [

221: ']',
222: '\\\'',
222: '\'',
224: 'Meta'

@@ -146,3 +147,3 @@ };

fixer.replaceText(node, 'key'),
fixer.replaceText(right, `'${keyCode}'`)
fixer.replaceText(right, quoteString(keyCode))
];

@@ -149,0 +150,0 @@ };

@@ -10,2 +10,3 @@ 'use strict';

'isArrayLikeObject',
'isBigInt',
'isBoolean',

@@ -12,0 +13,0 @@ 'isBuffer',

@@ -6,6 +6,2 @@ 'use strict';

const toPairs = require('lodash.topairs');
const camelCase = require('lodash.camelcase');
const kebabCase = require('lodash.kebabcase');
const upperfirst = require('lodash.upperfirst');
const snakeCase = require('lodash.snakecase');

@@ -15,6 +11,6 @@ const getDocsUrl = require('./utils/get-docs-url');

const pascalCase = string => upperfirst(camelCase(string));
const isPascalCase = string => string === pascalCase(string);
const isUpperCase = string => string === string.toUpperCase();
const isUpperFirst = string => isUpperCase(string[0]);
const lowerFirst = string => string[0].toLowerCase() + string.slice(1);
const upperFirst = string => string[0].toUpperCase() + string.slice(1);

@@ -87,2 +83,8 @@ const defaultReplacements = {

},
param: {
parameter: true
},
params: {
parameters: true
},
tbl: {

@@ -122,3 +124,4 @@ table: true

dir: {
directory: true
directory: true,
direction: true
},

@@ -158,2 +161,11 @@ dirs: {

},
curr: {
current: true
},
cur: {
current: true
},
acc: {
accumulator: true
},
rel: {

@@ -188,12 +200,2 @@ relative: true,

const getCase = string => {
for (const fn of [camelCase, kebabCase, snakeCase, upperfirst]) {
if (string === fn(string)) {
return fn;
}
}
return camelCase;
};
const prepareOptions = ({

@@ -240,144 +242,92 @@ checkProperties = true,

const normalizeName = name => {
let originalLeadingUnderscores;
let originalTrailingUnderscores;
([, originalLeadingUnderscores, name, originalTrailingUnderscores] = /^(_*)(.*?)(_*)$/.exec(name));
const getWordReplacements = (word, replacements) => {
const replacement = replacements.get(lowerFirst(word)) ||
replacements.get(word) ||
replacements.get(upperFirst(word));
const originalIsInPascalCase = isPascalCase(name);
if (originalIsInPascalCase) {
name = camelCase(name);
let wordReplacement = [];
if (replacement) {
wordReplacement = [...replacement.keys()]
.filter(name => replacement.get(name))
.map(isUpperFirst(word) ? upperFirst : lowerFirst);
}
return {
originalLeadingUnderscores,
originalTrailingUnderscores,
originalIsInPascalCase,
normalizedName: name
};
return wordReplacement.length > 0 ? wordReplacement.sort() : [];
};
const createApplyOriginalUnderscores = (originalLeadingUnderscores, originalTrailingUnderscores) => name => {
return originalLeadingUnderscores + name + originalTrailingUnderscores;
};
const getReplacementsFromCombinations = (combinations, length = Infinity) => {
const total = combinations.reduce((total, {length}) => total * length, 1);
const splitNormalizedName = normalizedName => {
return kebabCase(normalizedName).split('-');
const samples = Array.from({length: Math.min(total, length)}, (_, sampleIndex) => {
let indexLeft = sampleIndex;
return combinations.reduceRight((words, replacements) => {
const {length} = replacements;
const replacementIndex = indexLeft % length;
indexLeft -= replacementIndex;
indexLeft /= length;
return [replacements[replacementIndex], ...words];
}, []).join('');
});
return {
total,
samples
};
};
const getWordReplacements = (replacements, word) => {
const wordReplacements = replacements.get(word);
if (!wordReplacements) {
return [];
const getNameReplacements = (name, {replacements, whitelist}, limit = 3) => {
// Skip constants and whitelist
if (isUpperCase(name) || whitelist.get(name)) {
return {total: 0};
}
return [...wordReplacements.keys()].filter(name => wordReplacements.get(name));
};
// Find exact replacements
const exactReplacements = getWordReplacements(name, replacements);
/*
This function has terrible big O complexity, so we limit it by `limit`.
This is fine since result of the function is used only to check if there is zero, one or more replacements and when formating the message.
Example: `[[1, 2], [3, 4]]` → `[[1, 3], [1, 4], [2, 3], [2, 4]]`
*/
const getWordByWordReplacementsCombinations = (wordByWordReplacements, limit = 16) => {
if (wordByWordReplacements.length === 0) {
return [];
if (exactReplacements.length > 0) {
return {
total: exactReplacements.length,
samples: exactReplacements.slice(0, limit)
};
}
if (wordByWordReplacements.length === 1) {
return wordByWordReplacements[0];
}
// Split words
const words = name.split(/(?=[^a-z])|(?<=[^a-zA-Z])/g).filter(Boolean);
if (limit <= 1) {
return wordByWordReplacements[0];
}
let hasReplacements = false;
const combinations = words.map(word => {
const wordReplacements = getWordReplacements(word, replacements);
const [wordReplacements, ...tailWordReplacements] = wordByWordReplacements;
const tailCombinations = getWordByWordReplacementsCombinations(tailWordReplacements, limit / wordReplacements.length);
const result = [];
for (const name of wordReplacements) {
for (const combination of tailCombinations) {
result.push([name].concat(combination));
if (wordReplacements.length > 0) {
hasReplacements = true;
return wordReplacements;
}
}
return result;
};
return [word];
});
const getWordByWordReplacements = (replacements, normalizedName, originalIsInPascalCase) => {
const words = splitNormalizedName(normalizedName);
let wordByWordReplacements = words.map(word => getWordReplacements(replacements, word));
const someWordsHaveReplacements = wordByWordReplacements.some(wordReplacements => wordReplacements.length > 0);
if (!someWordsHaveReplacements) {
return [];
// No replacements for any word
if (!hasReplacements) {
return {total: 0};
}
wordByWordReplacements = wordByWordReplacements
.map((wordReplacements, i) => wordReplacements.length > 0 ? wordReplacements : [words[i]]);
return getWordByWordReplacementsCombinations(wordByWordReplacements)
.map(originalIsInPascalCase ? pascalCase : camelCase)
.sort();
return getReplacementsFromCombinations(combinations, limit);
};
const getExactReplacements = (replacements, normalizedName, originalIsInPascalCase) => {
const variableNameReplacements = replacements.get(normalizedName);
if (!variableNameReplacements) {
return [];
}
return [...variableNameReplacements.keys()]
.filter(name => variableNameReplacements.get(name))
.map(originalIsInPascalCase ? pascalCase : name => name)
.sort();
};
const getNameReplacements = (replacements, whitelist, name) => {
if (whitelist.get(name)) {
return [];
}
if (isUpperCase(name)) {
return [];
}
const {
originalLeadingUnderscores,
originalTrailingUnderscores,
originalIsInPascalCase,
normalizedName
} = normalizeName(name);
const applyOriginalUnderscores = createApplyOriginalUnderscores(originalLeadingUnderscores, originalTrailingUnderscores);
const exactReplacements = getExactReplacements(replacements, normalizedName, originalIsInPascalCase);
if (exactReplacements.length > 0) {
return exactReplacements.map(applyOriginalUnderscores);
}
return getWordByWordReplacements(replacements, normalizedName, originalIsInPascalCase).map(applyOriginalUnderscores);
};
const anotherNameMessage = 'A more descriptive name will do too.';
const formatMessage = (discouragedName, replacements, nameTypeText, replacementsLimit = 3) => {
const formatMessage = (discouragedName, replacements, nameTypeText) => {
const message = [];
const {total, samples = []} = replacements;
if (replacements.length === 1) {
message.push(`The ${nameTypeText} \`${discouragedName}\` should be named \`${replacements[0]}\`.`);
if (total === 1) {
message.push(`The ${nameTypeText} \`${discouragedName}\` should be named \`${samples[0]}\`.`);
} else {
let replacementsText = replacements.slice(0, replacementsLimit)
let replacementsText = samples
.map(replacement => `\`${replacement}\``)
.join(', ');
const omittedReplacementsCount = replacements.length - replacementsLimit;
const omittedReplacementsCount = total - samples.length;
if (omittedReplacementsCount > 0) {
replacementsText += `, ... (${omittedReplacementsCount} more omitted)`;
replacementsText += `, ... (${omittedReplacementsCount > 99 ? '99+' : omittedReplacementsCount} more omitted)`;
}

@@ -628,5 +578,5 @@

const variableReplacements = getNameReplacements(options.replacements, options.whitelist, variable.name);
const variableReplacements = getNameReplacements(variable.name, options);
if (variableReplacements.length === 0) {
if (variableReplacements.total === 0) {
return;

@@ -642,4 +592,4 @@ }

if (variableReplacements.length === 1 && shouldFix(variable)) {
const [replacement] = variableReplacements;
if (variableReplacements.total === 1 && shouldFix(variable)) {
const [replacement] = variableReplacements.samples;
const captureAvoidingReplacement = avoidCapture(replacement, scopes, ecmaVersion, isSafeName);

@@ -689,5 +639,5 @@

const identifierReplacements = getNameReplacements(options.replacements, options.whitelist, node.name);
const identifierReplacements = getNameReplacements(node.name, options);
if (identifierReplacements.length === 0) {
if (identifierReplacements.total === 0) {
return;

@@ -713,3 +663,3 @@ }

if (filenameWithExtension === '<input>') {
if (filenameWithExtension === '<input>' || filenameWithExtension === '<text>') {
return {};

@@ -720,18 +670,14 @@ }

const filename = path.basename(filenameWithExtension, extension);
const originalCase = getCase(filename);
const filenameReplacements = getNameReplacements(
options.replacements,
options.whitelist,
filename
)
.map(replacement => `${originalCase(replacement)}${extension}`);
const filenameReplacements = getNameReplacements(filename, options);
if (filenameReplacements.length === 0) {
if (filenameReplacements.total === 0) {
return;
}
filenameReplacements.samples = filenameReplacements.samples.map(replacement => `${replacement}${extension}`);
context.report({
node,
message: formatMessage(filenameWithExtension, filenameReplacements, 'file')
message: formatMessage(filenameWithExtension, filenameReplacements, 'filename')
});

@@ -738,0 +684,0 @@ },

'use strict';
const cleanRegexp = require('clean-regexp');
const getDocsUrl = require('./utils/get-docs-url');
const quoteString = require('./utils/quote-string');

@@ -54,6 +55,5 @@ const message = 'Use regex shorthands to improve readability.';

} else {
// Escape backslash and apostrophe because we wrap the result in single quotes
// Escape backslash
fixed = (newPattern || '').replace(/\\/g, '\\\\');
fixed = fixed.replace(/'/g, '\\\'');
fixed = `'${fixed}'`;
fixed = quoteString(fixed);
}

@@ -60,0 +60,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc