Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint

Package Overview
Dependencies
Maintainers
2
Versions
372
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint - npm Package Compare versions

Comparing version 9.9.1 to 9.10.0

lib/config/config.js

207

lib/config/flat-config-array.js

@@ -13,5 +13,5 @@ /**

const { ConfigArray, ConfigArraySymbol } = require("@eslint/config-array");
const { flatConfigSchema, hasMethod } = require("./flat-config-schema");
const { RuleValidator } = require("./rule-validator");
const { flatConfigSchema } = require("./flat-config-schema");
const { defaultConfig } = require("./default-config");
const { Config } = require("./config");

@@ -27,59 +27,3 @@ //-----------------------------------------------------------------------------

const ruleValidator = new RuleValidator();
/**
* Splits a plugin identifier in the form a/b/c into two parts: a/b and c.
* @param {string} identifier The identifier to parse.
* @returns {{objectName: string, pluginName: string}} The parts of the plugin
* name.
*/
function splitPluginIdentifier(identifier) {
const parts = identifier.split("/");
return {
objectName: parts.pop(),
pluginName: parts.join("/")
};
}
/**
* Returns the name of an object in the config by reading its `meta` key.
* @param {Object} object The object to check.
* @returns {string?} The name of the object if found or `null` if there
* is no name.
*/
function getObjectId(object) {
// first check old-style name
let name = object.name;
if (!name) {
if (!object.meta) {
return null;
}
name = object.meta.name;
if (!name) {
return null;
}
}
// now check for old-style version
let version = object.version;
if (!version) {
version = object.meta && object.meta.version;
}
// if there's a version then append that
if (version) {
return `${name}@${version}`;
}
return name;
}
/**
* Wraps a config error with details about where the error occurred.

@@ -128,39 +72,3 @@ * @param {Error} error The original error.

/**
* Converts a languageOptions object to a JSON representation.
* @param {Record<string, any>} languageOptions The options to create a JSON
* representation of.
* @param {string} objectKey The key of the object being converted.
* @returns {Record<string, any>} The JSON representation of the languageOptions.
* @throws {TypeError} If a function is found in the languageOptions.
*/
function languageOptionsToJSON(languageOptions, objectKey = "languageOptions") {
const result = {};
for (const [key, value] of Object.entries(languageOptions)) {
if (value) {
if (typeof value === "object") {
const name = getObjectId(value);
if (name && hasMethod(value)) {
result[key] = name;
} else {
result[key] = languageOptionsToJSON(value, key);
}
continue;
}
if (typeof value === "function") {
throw new TypeError(`Cannot serialize key "${key}" in ${objectKey}: Function values are not supported.`);
}
}
result[key] = value;
}
return result;
}
const originalBaseConfig = Symbol("originalBaseConfig");

@@ -311,112 +219,3 @@ const originalLength = Symbol("originalLength");

[ConfigArraySymbol.finalizeConfig](config) {
const { plugins, language, languageOptions, processor } = config;
let parserName, processorName, languageName;
let invalidParser = false,
invalidProcessor = false,
invalidLanguage = false;
// Check parser value
if (languageOptions && languageOptions.parser) {
const { parser } = languageOptions;
if (typeof parser === "object") {
parserName = getObjectId(parser);
if (!parserName) {
invalidParser = true;
}
} else {
invalidParser = true;
}
}
// Check language value
if (language) {
if (typeof language === "string") {
const { pluginName, objectName: localLanguageName } = splitPluginIdentifier(language);
languageName = language;
if (!plugins || !plugins[pluginName] || !plugins[pluginName].languages || !plugins[pluginName].languages[localLanguageName]) {
throw new TypeError(`Key "language": Could not find "${localLanguageName}" in plugin "${pluginName}".`);
}
config.language = plugins[pluginName].languages[localLanguageName];
} else {
invalidLanguage = true;
}
try {
config.language.validateLanguageOptions(config.languageOptions);
} catch (error) {
throw new TypeError(`Key "languageOptions": ${error.message}`, { cause: error });
}
}
// Check processor value
if (processor) {
if (typeof processor === "string") {
const { pluginName, objectName: localProcessorName } = splitPluginIdentifier(processor);
processorName = processor;
if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[localProcessorName]) {
throw new TypeError(`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`);
}
config.processor = plugins[pluginName].processors[localProcessorName];
} else if (typeof processor === "object") {
processorName = getObjectId(processor);
if (!processorName) {
invalidProcessor = true;
}
} else {
invalidProcessor = true;
}
}
ruleValidator.validate(config);
// apply special logic for serialization into JSON
/* eslint-disable object-shorthand -- shorthand would change "this" value */
Object.defineProperty(config, "toJSON", {
value: function() {
if (invalidParser) {
throw new Error("Could not serialize parser object (missing 'meta' object).");
}
if (invalidProcessor) {
throw new Error("Could not serialize processor object (missing 'meta' object).");
}
if (invalidLanguage) {
throw new Error("Caching is not supported when language is an object.");
}
return {
...this,
plugins: Object.entries(plugins).map(([namespace, plugin]) => {
const pluginId = getObjectId(plugin);
if (!pluginId) {
return namespace;
}
return `${namespace}:${pluginId}`;
}),
language: languageName,
languageOptions: languageOptionsToJSON(languageOptions),
processor: processorName
};
}
});
/* eslint-enable object-shorthand -- ok to enable now */
return config;
return new Config(config);
}

@@ -423,0 +222,0 @@ /* eslint-enable class-methods-use-this -- Desired as instance method */

@@ -23,3 +23,3 @@ /**

createEmitter = require("../../../linter/safe-emitter"),
ConfigCommentParser = require("../../../linter/config-comment-parser"),
{ ConfigCommentParser, VisitNodeStep, CallMethodStep } = require("@eslint/plugin-kit"),

@@ -320,62 +320,3 @@ eslintScope = require("eslint-scope");

const STEP_KIND = {
visit: 1,
call: 2
};
/**
* A class to represent a step in the traversal process.
*/
class TraversalStep {
/**
* The type of the step.
* @type {string}
*/
type;
/**
* The kind of the step. Represents the same data as the `type` property
* but it's a number for performance.
* @type {number}
*/
kind;
/**
* The target of the step.
* @type {ASTNode|string}
*/
target;
/**
* The phase of the step.
* @type {number|undefined}
*/
phase;
/**
* The arguments of the step.
* @type {Array<any>}
*/
args;
/**
* Creates a new instance.
* @param {Object} options The options for the step.
* @param {string} options.type The type of the step.
* @param {ASTNode|string} options.target The target of the step.
* @param {number|undefined} [options.phase] The phase of the step.
* @param {Array<any>} options.args The arguments of the step.
* @returns {void}
*/
constructor({ type, target, phase, args }) {
this.type = type;
this.kind = STEP_KIND[type];
this.target = target;
this.phase = phase;
this.args = args;
}
}
/**
* A class to represent a directive comment.

@@ -1007,7 +948,9 @@ * @implements {IDirective}

const { directivePart } = commentParser.extractDirectiveComment(comment.value);
const directive = commentParser.parseDirective(comment.value);
const directiveMatch = directivesPattern.exec(directivePart);
if (!directive) {
return false;
}
if (!directiveMatch) {
if (!directivesPattern.test(directive.label)) {
return false;

@@ -1017,3 +960,3 @@ }

// only certain comment types are supported as line comments
return comment.type !== "Line" || !!/^eslint-disable-(next-)?line$/u.test(directiveMatch[1]);
return comment.type !== "Line" || !!/^eslint-disable-(next-)?line$/u.test(directive.label);
});

@@ -1045,15 +988,12 @@

this.getInlineConfigNodes().forEach(comment => {
const { directivePart, justificationPart } = commentParser.extractDirectiveComment(comment.value);
// Step 1: Extract the directive text
const match = directivesPattern.exec(directivePart);
// Step 1: Parse the directive
const {
label,
value,
justification: justificationPart
} = commentParser.parseDirective(comment.value);
if (!match) {
return;
}
const directiveText = match[1];
// Step 2: Extract the directive value
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(directiveText);
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(label);

@@ -1065,4 +1005,4 @@ if (comment.type === "Line" && !lineCommentSupported) {

// Step 3: Validate the directive does not span multiple lines
if (directiveText === "eslint-disable-line" && comment.loc.start.line !== comment.loc.end.line) {
const message = `${directiveText} comment should not span multiple lines.`;
if (label === "eslint-disable-line" && comment.loc.start.line !== comment.loc.end.line) {
const message = `${label} comment should not span multiple lines.`;

@@ -1078,5 +1018,3 @@ problems.push({

// Step 4: Extract the directive value and create the Directive object
const directiveValue = directivePart.slice(match.index + directiveText.length);
switch (directiveText) {
switch (label) {
case "eslint-disable":

@@ -1086,3 +1024,3 @@ case "eslint-enable":

case "eslint-disable-line": {
const directiveType = directiveText.slice("eslint-".length);
const directiveType = label.slice("eslint-".length);

@@ -1092,3 +1030,3 @@ directives.push(new Directive({

node: comment,
value: directiveValue,
value,
justification: justificationPart

@@ -1148,7 +1086,7 @@ }));

const { directiveText, directiveValue } = commentParser.parseDirective(comment);
const { label, value } = commentParser.parseDirective(comment.value);
switch (directiveText) {
switch (label) {
case "exported":
Object.assign(exportedVariables, commentParser.parseListConfig(directiveValue, comment));
Object.assign(exportedVariables, commentParser.parseListConfig(value));
break;

@@ -1158,7 +1096,7 @@

case "global":
for (const [id, { value }] of Object.entries(commentParser.parseStringConfig(directiveValue, comment))) {
for (const [id, idSetting] of Object.entries(commentParser.parseStringConfig(value))) {
let normalizedValue;
try {
normalizedValue = normalizeConfigGlobal(value);
normalizedValue = normalizeConfigGlobal(idSetting);
} catch (err) {

@@ -1186,5 +1124,5 @@ problems.push({

case "eslint": {
const parseResult = commentParser.parseJsonConfig(directiveValue);
const parseResult = commentParser.parseJSONLikeConfig(value);
if (parseResult.success) {
if (parseResult.ok) {
configs.push({

@@ -1266,4 +1204,3 @@ config: {

enterNode(node) {
steps.push(new TraversalStep({
type: "visit",
steps.push(new VisitNodeStep({
target: node,

@@ -1275,4 +1212,3 @@ phase: 1,

leaveNode(node) {
steps.push(new TraversalStep({
type: "visit",
steps.push(new VisitNodeStep({
target: node,

@@ -1300,4 +1236,3 @@ phase: 2,

emitter.on(eventName, (...args) => {
steps.push(new TraversalStep({
type: "call",
steps.push(new CallMethodStep({
target: eventName,

@@ -1304,0 +1239,0 @@ args

@@ -63,21 +63,10 @@ /**

* @param {Directive[]} directives Unused directives to be removed.
* @param {Token} node The backing Comment token.
* @param {{node: Token, value: string}} parentDirective Data about the backing directive.
* @param {SourceCode} sourceCode The source code object for the file being linted.
* @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
*/
function createIndividualDirectivesRemoval(directives, node, sourceCode) {
function createIndividualDirectivesRemoval(directives, parentDirective, sourceCode) {
const range = sourceCode.getRange(node);
/*
* `node.value` starts right after `//` or `/*`.
* All calculated offsets will be relative to this index.
*/
const commentValueStart = range[0] + "//".length;
// Find where the list of rules starts. `\S+` matches with the directive name (e.g. `eslint-disable-line`)
const listStartOffset = /^\s*\S+\s+/u.exec(node.value)[0].length;
/*
* Get the list text without any surrounding whitespace. In order to preserve the original
* Get the list of the rules text without any surrounding whitespace. In order to preserve the original
* formatting, we don't want to change that whitespace.

@@ -88,7 +77,7 @@ *

*/
const listText = node.value
.slice(listStartOffset) // remove directive name and all whitespace before the list
.split(/\s-{2,}\s/u)[0] // remove `-- comment`, if it exists
.trimEnd(); // remove all whitespace after the list
const listText = parentDirective.value.trim();
// Calculate where it starts in the source code text
const listStart = sourceCode.text.indexOf(listText, sourceCode.getRange(parentDirective.node)[0]);
/*

@@ -106,4 +95,4 @@ * We can assume that `listText` contains multiple elements.

const matchedText = match[0];
const matchStartOffset = listStartOffset + match.index;
const matchEndOffset = matchStartOffset + matchedText.length;
const matchStart = listStart + match.index;
const matchEnd = matchStart + matchedText.length;

@@ -113,3 +102,3 @@ const firstIndexOfComma = matchedText.indexOf(",");

let removalStartOffset, removalEndOffset;
let removalStart, removalEnd;

@@ -130,4 +119,4 @@ if (firstIndexOfComma !== lastIndexOfComma) {

*/
removalStartOffset = matchStartOffset + firstIndexOfComma;
removalEndOffset = matchStartOffset + lastIndexOfComma;
removalStart = matchStart + firstIndexOfComma;
removalEnd = matchStart + lastIndexOfComma;

@@ -154,4 +143,4 @@ } else {

*/
removalStartOffset = matchStartOffset;
removalEndOffset = matchEndOffset;
removalStart = matchStart;
removalEnd = matchEnd;
}

@@ -163,4 +152,4 @@

range: [
commentValueStart + removalStartOffset,
commentValueStart + removalEndOffset
removalStart,
removalEnd
],

@@ -216,3 +205,3 @@ text: ""

return remainingRuleIds.size
? createIndividualDirectivesRemoval(directives, parentDirective.node, sourceCode)
? createIndividualDirectivesRemoval(directives, parentDirective, sourceCode)
: [createDirectiveRemoval(directives, parentDirective.node, sourceCode)];

@@ -219,0 +208,0 @@ }

@@ -120,2 +120,3 @@ /**

ImportDefaultSpecifier: true,
ImportNamespaceSpecifier: true,
RestElement: true,

@@ -122,0 +123,0 @@ FunctionExpression: true,

@@ -13,3 +13,3 @@ /**

const validator = new RegExpValidator();
const validFlags = /[dgimsuvy]/gu;
const validFlags = "dgimsuvy";
const undefined1 = void 0;

@@ -53,9 +53,9 @@

const options = context.options[0];
let allowedFlags = null;
let allowedFlags = [];
if (options && options.allowConstructorFlags) {
const temp = options.allowConstructorFlags.join("").replace(validFlags, "");
const temp = options.allowConstructorFlags.join("").replace(new RegExp(`[${validFlags}]`, "gu"), "");
if (temp) {
allowedFlags = new RegExp(`[${temp}]`, "gu");
allowedFlags = [...new Set(temp)];
}

@@ -130,13 +130,16 @@ }

* @param {string|null} flags The RegExp flags to validate.
* @param {string|null} flagsToCheck The RegExp invalid flags.
* @param {string} allFlags all valid and allowed flags.
* @returns {string|null} The syntax error.
*/
function validateRegExpFlags(flags) {
if (!flags) {
return null;
function validateRegExpFlags(flags, flagsToCheck, allFlags) {
const duplicateFlags = [];
if (typeof flagsToCheck === "string") {
for (const flag of flagsToCheck) {
if (allFlags.includes(flag)) {
duplicateFlags.push(flag);
}
}
}
try {
validator.validateFlags(flags);
} catch {
return `Invalid flags supplied to RegExp constructor '${flags}'`;
}

@@ -148,6 +151,15 @@ /*

*/
if (flags.includes("u") && flags.includes("v")) {
if (flags && flags.includes("u") && flags.includes("v")) {
return "Regex 'u' and 'v' flags cannot be used together";
}
return null;
if (duplicateFlags.length > 0) {
return `Duplicate flags ('${duplicateFlags.join("")}') supplied to RegExp constructor`;
}
if (!flagsToCheck) {
return null;
}
return `Invalid flags supplied to RegExp constructor '${flagsToCheck}'`;
}

@@ -161,9 +173,13 @@

let flags = getFlags(node);
const flags = getFlags(node);
let flagsToCheck = flags;
const allFlags = allowedFlags.length > 0 ? validFlags.split("").concat(allowedFlags) : validFlags.split("");
if (flags && allowedFlags) {
flags = flags.replace(allowedFlags, "");
if (flags) {
allFlags.forEach(flag => {
flagsToCheck = flagsToCheck.replace(flag, "");
});
}
let message = validateRegExpFlags(flags);
let message = validateRegExpFlags(flags, flagsToCheck, allFlags);

@@ -170,0 +186,0 @@ if (message) {

@@ -21,2 +21,22 @@ /**

/**
* Checks whether the flag configuration should be treated as a missing flag.
* @param {"u"|"v"|undefined} requireFlag A particular flag to require
* @param {string} flags The regex flags
* @returns {boolean} Whether the flag configuration results in a missing flag.
*/
function checkFlags(requireFlag, flags) {
let missingFlag;
if (requireFlag === "v") {
missingFlag = !flags.includes("v");
} else if (requireFlag === "u") {
missingFlag = !flags.includes("u");
} else {
missingFlag = !flags.includes("u") && !flags.includes("v");
}
return missingFlag;
}
//------------------------------------------------------------------------------

@@ -41,6 +61,18 @@ // Rule Definition

addUFlag: "Add the 'u' flag.",
requireUFlag: "Use the 'u' flag."
addVFlag: "Add the 'v' flag.",
requireUFlag: "Use the 'u' flag.",
requireVFlag: "Use the 'v' flag."
},
schema: []
schema: [
{
type: "object",
properties: {
requireFlag: {
enum: ["u", "v"]
}
},
additionalProperties: false
}
]
},

@@ -52,2 +84,6 @@

const {
requireFlag
} = context.options[0] ?? {};
return {

@@ -57,13 +93,31 @@ "Literal[regex]"(node) {

if (!flags.includes("u") && !flags.includes("v")) {
const missingFlag = checkFlags(requireFlag, flags);
if (missingFlag) {
context.report({
messageId: "requireUFlag",
messageId: requireFlag === "v" ? "requireVFlag" : "requireUFlag",
node,
suggest: isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, node.regex.pattern)
suggest: isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, node.regex.pattern, requireFlag)
? [
{
fix(fixer) {
return fixer.insertTextAfter(node, "u");
const replaceFlag = requireFlag ?? "u";
const regex = sourceCode.getText(node);
const slashPos = regex.lastIndexOf("/");
if (requireFlag) {
const flag = requireFlag === "u" ? "v" : "u";
if (regex.includes(flag, slashPos)) {
return fixer.replaceText(
node,
regex.slice(0, slashPos) +
regex.slice(slashPos).replace(flag, requireFlag)
);
}
}
return fixer.insertTextAfter(node, replaceFlag);
},
messageId: "addUFlag"
messageId: requireFlag === "v" ? "addVFlag" : "addUFlag"
}

@@ -92,18 +146,45 @@ ]

if (!flagsNode || (typeof flags === "string" && !flags.includes("u") && !flags.includes("v"))) {
let missingFlag = !flagsNode;
if (typeof flags === "string") {
missingFlag = checkFlags(requireFlag, flags);
}
if (missingFlag) {
context.report({
messageId: "requireUFlag",
messageId: requireFlag === "v" ? "requireVFlag" : "requireUFlag",
node: refNode,
suggest: typeof pattern === "string" && isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, pattern)
suggest: typeof pattern === "string" && isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, pattern, requireFlag)
? [
{
fix(fixer) {
const replaceFlag = requireFlag ?? "u";
if (flagsNode) {
if ((flagsNode.type === "Literal" && typeof flagsNode.value === "string") || flagsNode.type === "TemplateLiteral") {
const flagsNodeText = sourceCode.getText(flagsNode);
const flag = requireFlag === "u" ? "v" : "u";
if (flags.includes(flag)) {
// Avoid replacing "u" in escapes like `\uXXXX`
if (flagsNode.type === "Literal" && flagsNode.raw.includes("\\")) {
return null;
}
// Avoid replacing "u" in expressions like "`${regularFlags}g`"
if (flagsNode.type === "TemplateLiteral" && (
flagsNode.expressions.length ||
flagsNode.quasis.some(({ value: { raw } }) => raw.includes("\\"))
)) {
return null;
}
return fixer.replaceText(flagsNode, flagsNodeText.replace(flag, replaceFlag));
}
return fixer.replaceText(flagsNode, [
flagsNodeText.slice(0, flagsNodeText.length - 1),
flagsNodeText.slice(flagsNodeText.length - 1)
].join("u"));
].join(replaceFlag));
}

@@ -120,7 +201,7 @@

astUtils.isCommaToken(penultimateToken)
? ' "u",'
: ', "u"'
? ` "${replaceFlag}",`
: `, "${replaceFlag}"`
);
},
messageId: "addUFlag"
messageId: requireFlag === "v" ? "addVFlag" : "addUFlag"
}

@@ -127,0 +208,0 @@ ]

@@ -17,2 +17,3 @@ /**

* @param {string} pattern The regular expression pattern to verify.
* @param {"u"|"v"} flag The type of Unicode flag
* @returns {boolean} `true` if the pattern would be valid with the `u` flag.

@@ -22,6 +23,9 @@ * `false` if the pattern would be invalid with the `u` flag or the configured

*/
function isValidWithUnicodeFlag(ecmaVersion, pattern) {
if (ecmaVersion <= 5) { // ecmaVersion <= 5 doesn't support the 'u' flag
function isValidWithUnicodeFlag(ecmaVersion, pattern, flag = "u") {
if (flag === "u" && ecmaVersion <= 5) { // ecmaVersion <= 5 doesn't support the 'u' flag
return false;
}
if (flag === "v" && ecmaVersion <= 2023) {
return false;
}

@@ -33,3 +37,7 @@ const validator = new RegExpValidator({

try {
validator.validatePattern(pattern, void 0, void 0, { unicode: /* uFlag = */ true });
validator.validatePattern(pattern, void 0, void 0, flag === "u" ? {
unicode: /* uFlag = */ true
} : {
unicodeSets: true
});
} catch {

@@ -36,0 +44,0 @@ return false;

{
"name": "eslint",
"version": "9.9.1",
"version": "9.10.0",
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",

@@ -10,6 +10,16 @@ "description": "An AST-based pattern checker for JavaScript.",

"main": "./lib/api.js",
"types": "./lib/types/index.d.ts",
"exports": {
".": {
"types": "./lib/types/index.d.ts",
"default": "./lib/api.js"
},
"./package.json": "./package.json",
".": "./lib/api.js",
"./use-at-your-own-risk": "./lib/unsupported-api.js"
"./use-at-your-own-risk": {
"types": "./lib/types/use-at-your-own-risk.d.ts",
"default": "./lib/unsupported-api.js"
},
"./rules": {
"types": "./lib/types/rules/index.d.ts"
}
},

@@ -38,3 +48,4 @@ "scripts": {

"test:performance": "node Makefile.js perf",
"test:emfile": "node tools/check-emfile-handling.js"
"test:emfile": "node tools/check-emfile-handling.js",
"test:types": "tsc -p tests/lib/types/tsconfig.json"
},

@@ -75,3 +86,4 @@ "gitHooks": {

"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "9.9.1",
"@eslint/js": "9.10.0",
"@eslint/plugin-kit": "^0.1.0",
"@humanwhocodes/module-importer": "^1.0.1",

@@ -99,3 +111,2 @@ "@humanwhocodes/retry": "^0.3.0",

"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash.merge": "^4.6.2",

@@ -111,6 +122,7 @@ "minimatch": "^3.1.2",

"@babel/preset-env": "^7.4.3",
"@eslint/core": "^0.4.0",
"@eslint/json": "^0.3.0",
"@eslint/core": "^0.5.0",
"@eslint/json": "^0.4.0",
"@trunkio/launcher": "^1.3.0",
"@types/estree": "^1.0.5",
"@types/json-schema": "^7.0.15",
"@types/node": "^20.11.5",

@@ -117,0 +129,0 @@ "@wdio/browser-runner": "^9.0.5",

@@ -300,5 +300,5 @@ [![npm version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint)

<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
<p><a href="#"><img src="https://images.opencollective.com/guest-bf377e88/avatar.png" alt="Eli Schleifer" height="96"></a> <a href="https://opensource.siemens.com"><img src="https://avatars.githubusercontent.com/u/624020?v=4" alt="Siemens" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a> <a href="https://opensource.siemens.com"><img src="https://avatars.githubusercontent.com/u/624020?v=4" alt="Siemens" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a> <a href="https://www.workleap.com"><img src="https://avatars.githubusercontent.com/u/53535748?u=d1e55d7661d724bf2281c1bfd33cb8f99fe2465f&v=4" alt="Workleap" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://www.notion.so"><img src="https://images.opencollective.com/notion/bf3b117/logo.png" alt="notion" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://usenextbase.com"><img src="https://avatars.githubusercontent.com/u/145838380?v=4" alt="Nextbase Starter Kit" height="32"></a></p>
<p><a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://usenextbase.com"><img src="https://avatars.githubusercontent.com/u/145838380?v=4" alt="Nextbase Starter Kit" height="32"></a></p>
<!--sponsorsend-->

@@ -305,0 +305,0 @@

Sorry, the diff of this file is too big to display

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