You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@eslint/config-array

Package Overview
Dependencies
Maintainers
2
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eslint/config-array - npm Package Compare versions

Comparing version
0.23.2
to
0.23.3
+29
-24
dist/cjs/index.cjs

@@ -206,2 +206,5 @@ 'use strict';

/** @typedef {$typests.ConfigObject} ConfigObject */
/** @typedef {$typests.FileMatcher} FileMatcher */
/** @typedef {$typests.FilesMatcher} FilesMatcher */
/** @typedef {$typests.ExtraConfigType} ExtraConfigType */
/** @import * as $minimatch from "minimatch"; */

@@ -249,3 +252,3 @@ /** @typedef {$minimatch.MinimatchOptions} MinimatchOptions */

* The types of config objects that are supported.
* @type {Set<string>}
* @type {Set<ExtraConfigType>}
*/

@@ -335,3 +338,3 @@ const CONFIG_TYPES = new Set(["array", "function"]);

* Rethrows a config error with additional information about the config object.
* @param {object} config The config object to get the name of.
* @param {ConfigObject} config The config object to get the name of.
* @param {number} index The index of the config object in the array.

@@ -349,3 +352,3 @@ * @param {Error} error The error to rethrow.

* @param {any} value The value to check.
* @returns {boolean} True if a string, false if not.
* @returns {value is string} True if a string, false if not.
*/

@@ -410,4 +413,4 @@ function isString(value) {

* @param {string} pattern The glob pattern to match against.
* @param {object} options The minimatch options to use.
* @returns
* @param {MinimatchOptions} options The minimatch options to use.
* @returns {boolean} True if the file path matches, false if not.
*/

@@ -436,4 +439,4 @@ function doMatch(filepath, pattern, options = {}) {

* Normalizes a pattern by removing the leading "./" if present.
* @param {string} pattern The pattern to normalize.
* @returns {string} The normalized pattern.
* @param {FileMatcher} pattern The pattern to normalize.
* @returns {FileMatcher} The normalized pattern.
*/

@@ -539,3 +542,3 @@ function normalizePattern(pattern) {

* found.
* @param {Array<string>} extraConfigTypes The config types to check.
* @param {ReadonlyArray<ExtraConfigType>} extraConfigTypes The config types to check.
* @param {string} namespacedBasePath The namespaced base path of the directory to which config base paths are relative.

@@ -588,3 +591,3 @@ * @param {PathImpl} path Path-handling implementation.

*/
const asyncIterable = await flatTraverse(items);
const asyncIterable = flatTraverse(items);
const configs = [];

@@ -605,3 +608,3 @@

* found.
* @param {Array<string>} extraConfigTypes The config types to check.
* @param {ReadonlyArray<ExtraConfigType>} extraConfigTypes The config types to check.
* @param {string} namespacedBasePath The namespaced base path of the directory to which config base paths are relative.

@@ -679,3 +682,3 @@ * @param {PathImpl} path Path-handling implementation

* matcher.
* @param {Array<{ basePath?: string, ignores: Array<string|((string) => boolean)>}>} configs Configuration objects containing `ignores`.
* @param {Array<{ basePath?: string, ignores: FileMatcher[] }>} configs Configuration objects containing `ignores`.
* @param {string} filePath The unprocessed file path to check.

@@ -686,3 +689,3 @@ * @param {string} relativeFilePath The path of the file to check relative to the base path,

* that have `basePath` property.
* @param {string} [basePathData.basePath] Namespaced path to witch `relativeFilePath` is relative.
* @param {string} [basePathData.basePath] Namespaced path to which `relativeFilePath` is relative.
* @param {PathImpl} [basePathData.path] Path-handling implementation.

@@ -756,3 +759,3 @@ * @returns {boolean} True if the path should be ignored and false if not.

* using forward slash (`"/"`) as a separator.
* @param {Object} config The config object to check.
* @param {ConfigObject & { files: FilesMatcher[] }} config The config object to check.
* @returns {boolean} True if the file path is matched by the config,

@@ -820,3 +823,3 @@ * false if not.

* Ensures that config types are valid.
* @param {Array<string>} extraConfigTypes The config types to check.
* @param {ReadonlyArray<ExtraConfigType>} extraConfigTypes The config types to check.
* @returns {void}

@@ -826,6 +829,8 @@ * @throws {TypeError} When the config types array is invalid.

function assertExtraConfigTypes(extraConfigTypes) {
if (!Array.isArray(extraConfigTypes)) {
throw new TypeError("extraConfigTypes must be an array.");
}
if (extraConfigTypes.length > 2) {
throw new TypeError(
"configTypes must be an array with at most two items.",
);
throw new TypeError("extraConfigTypes must contain at most two items.");
}

@@ -836,3 +841,3 @@

throw new TypeError(
`Unexpected config type "${configType}" found. Expected one of: "object", "array", "function".`,
`Unexpected config type "${configType}" in extraConfigTypes. Expected one of: "array", "function".`,
);

@@ -908,5 +913,5 @@ }

* configs have already been normalized.
* @param {Object} [options.schema] The additional schema
* @param {ObjectDefinition} [options.schema] The additional schema
* definitions to use for the ConfigArray schema.
* @param {Array<string>} [options.extraConfigTypes] List of config types supported.
* @param {ReadonlyArray<ExtraConfigType>} [options.extraConfigTypes] List of config types supported.
* @throws {TypeError} When the `basePath` is not a non-empty string,

@@ -959,3 +964,3 @@ */

* The supported config types.
* @type {Array<string>}
* @type {ReadonlyArray<ExtraConfigType>}
*/

@@ -1013,3 +1018,3 @@ this.extraConfigTypes = [...extraConfigTypes];

* for a command line interface.
* @returns {Array<string|Function>} An array of matchers.
* @returns {Array<FilesMatcher>} An array of matchers.
*/

@@ -1050,3 +1055,3 @@ get files() {

* globbing operation to be faster.
* @returns {Object[]} An array of config objects representing global ignores.
* @returns {Array<{ basePath?: string, name?: string, ignores: FileMatcher[] }>} An array of config objects representing global ignores.
*/

@@ -1070,3 +1075,3 @@ get ignores() {

* We only count ignores if there are no other keys in the object.
* In this case, it acts list a globally ignored pattern. If there
* In this case, it acts like a globally ignored pattern. If there
* are additional keys, then ignores act like exclusions.

@@ -1073,0 +1078,0 @@ */

@@ -5,2 +5,5 @@ export { ObjectSchema } from "@eslint/object-schema";

export type ConfigObject = $typests.ConfigObject;
export type FileMatcher = $typests.FileMatcher;
export type FilesMatcher = $typests.FilesMatcher;
export type ExtraConfigType = $typests.ExtraConfigType;
export type MinimatchOptions = $minimatch.MinimatchOptions;

@@ -22,5 +25,5 @@ export type ObjectSchemaInstance = ObjectSchema;

* configs have already been normalized.
* @param {Object} [options.schema] The additional schema
* @param {ObjectDefinition} [options.schema] The additional schema
* definitions to use for the ConfigArray schema.
* @param {Array<string>} [options.extraConfigTypes] List of config types supported.
* @param {ReadonlyArray<ExtraConfigType>} [options.extraConfigTypes] List of config types supported.
* @throws {TypeError} When the `basePath` is not a non-empty string,

@@ -31,4 +34,4 @@ */

normalized?: boolean;
schema?: any;
extraConfigTypes?: Array<string>;
schema?: ObjectDefinition;
extraConfigTypes?: ReadonlyArray<ExtraConfigType>;
});

@@ -44,5 +47,5 @@ /**

* The supported config types.
* @type {Array<string>}
* @type {ReadonlyArray<ExtraConfigType>}
*/
extraConfigTypes: Array<string>;
extraConfigTypes: ReadonlyArray<ExtraConfigType>;
/**

@@ -53,5 +56,5 @@ * Returns the `files` globs from every config object in the array.

* for a command line interface.
* @returns {Array<string|Function>} An array of matchers.
* @returns {Array<FilesMatcher>} An array of matchers.
*/
get files(): Array<string | Function>;
get files(): Array<FilesMatcher>;
/**

@@ -62,5 +65,9 @@ * Returns ignore matchers that should always be ignored regardless of

* globbing operation to be faster.
* @returns {Object[]} An array of config objects representing global ignores.
* @returns {Array<{ basePath?: string, name?: string, ignores: FileMatcher[] }>} An array of config objects representing global ignores.
*/
get ignores(): any[];
get ignores(): Array<{
basePath?: string;
name?: string;
ignores: FileMatcher[];
}>;
/**

@@ -67,0 +74,0 @@ * Indicates if the config array has been normalized.

@@ -6,2 +6,19 @@ /**

/**
* A file matcher used in `files` and `ignores`.
*/
export type FileMatcher = string | ((filePath: string) => boolean);
/**
* An entry in a config's `files` array.
*
* A subarray means all matchers must match.
*/
export type FilesMatcher = FileMatcher | FileMatcher[];
/**
* The config types allowed in the `extraConfigTypes` option.
*/
export type ExtraConfigType = "array" | "function";
export interface ConfigObject {

@@ -16,3 +33,3 @@ /**

*/
files?: string[];
files?: FilesMatcher[];

@@ -22,3 +39,3 @@ /**

*/
ignores?: string[];
ignores?: FileMatcher[];

@@ -25,0 +42,0 @@ /**

@@ -5,2 +5,5 @@ export { ObjectSchema } from "@eslint/object-schema";

export type ConfigObject = $typests.ConfigObject;
export type FileMatcher = $typests.FileMatcher;
export type FilesMatcher = $typests.FilesMatcher;
export type ExtraConfigType = $typests.ExtraConfigType;
export type MinimatchOptions = $minimatch.MinimatchOptions;

@@ -22,5 +25,5 @@ export type ObjectSchemaInstance = ObjectSchema;

* configs have already been normalized.
* @param {Object} [options.schema] The additional schema
* @param {ObjectDefinition} [options.schema] The additional schema
* definitions to use for the ConfigArray schema.
* @param {Array<string>} [options.extraConfigTypes] List of config types supported.
* @param {ReadonlyArray<ExtraConfigType>} [options.extraConfigTypes] List of config types supported.
* @throws {TypeError} When the `basePath` is not a non-empty string,

@@ -31,4 +34,4 @@ */

normalized?: boolean;
schema?: any;
extraConfigTypes?: Array<string>;
schema?: ObjectDefinition;
extraConfigTypes?: ReadonlyArray<ExtraConfigType>;
});

@@ -44,5 +47,5 @@ /**

* The supported config types.
* @type {Array<string>}
* @type {ReadonlyArray<ExtraConfigType>}
*/
extraConfigTypes: Array<string>;
extraConfigTypes: ReadonlyArray<ExtraConfigType>;
/**

@@ -53,5 +56,5 @@ * Returns the `files` globs from every config object in the array.

* for a command line interface.
* @returns {Array<string|Function>} An array of matchers.
* @returns {Array<FilesMatcher>} An array of matchers.
*/
get files(): Array<string | Function>;
get files(): Array<FilesMatcher>;
/**

@@ -62,5 +65,9 @@ * Returns ignore matchers that should always be ignored regardless of

* globbing operation to be faster.
* @returns {Object[]} An array of config objects representing global ignores.
* @returns {Array<{ basePath?: string, name?: string, ignores: FileMatcher[] }>} An array of config objects representing global ignores.
*/
get ignores(): any[];
get ignores(): Array<{
basePath?: string;
name?: string;
ignores: FileMatcher[];
}>;
/**

@@ -67,0 +74,0 @@ * Indicates if the config array has been normalized.

@@ -186,2 +186,5 @@ // @ts-self-types="./index.d.ts"

/** @typedef {$typests.ConfigObject} ConfigObject */
/** @typedef {$typests.FileMatcher} FileMatcher */
/** @typedef {$typests.FilesMatcher} FilesMatcher */
/** @typedef {$typests.ExtraConfigType} ExtraConfigType */
/** @import * as $minimatch from "minimatch"; */

@@ -229,3 +232,3 @@ /** @typedef {$minimatch.MinimatchOptions} MinimatchOptions */

* The types of config objects that are supported.
* @type {Set<string>}
* @type {Set<ExtraConfigType>}
*/

@@ -315,3 +318,3 @@ const CONFIG_TYPES = new Set(["array", "function"]);

* Rethrows a config error with additional information about the config object.
* @param {object} config The config object to get the name of.
* @param {ConfigObject} config The config object to get the name of.
* @param {number} index The index of the config object in the array.

@@ -329,3 +332,3 @@ * @param {Error} error The error to rethrow.

* @param {any} value The value to check.
* @returns {boolean} True if a string, false if not.
* @returns {value is string} True if a string, false if not.
*/

@@ -390,4 +393,4 @@ function isString(value) {

* @param {string} pattern The glob pattern to match against.
* @param {object} options The minimatch options to use.
* @returns
* @param {MinimatchOptions} options The minimatch options to use.
* @returns {boolean} True if the file path matches, false if not.
*/

@@ -416,4 +419,4 @@ function doMatch(filepath, pattern, options = {}) {

* Normalizes a pattern by removing the leading "./" if present.
* @param {string} pattern The pattern to normalize.
* @returns {string} The normalized pattern.
* @param {FileMatcher} pattern The pattern to normalize.
* @returns {FileMatcher} The normalized pattern.
*/

@@ -519,3 +522,3 @@ function normalizePattern(pattern) {

* found.
* @param {Array<string>} extraConfigTypes The config types to check.
* @param {ReadonlyArray<ExtraConfigType>} extraConfigTypes The config types to check.
* @param {string} namespacedBasePath The namespaced base path of the directory to which config base paths are relative.

@@ -568,3 +571,3 @@ * @param {PathImpl} path Path-handling implementation.

*/
const asyncIterable = await flatTraverse(items);
const asyncIterable = flatTraverse(items);
const configs = [];

@@ -585,3 +588,3 @@

* found.
* @param {Array<string>} extraConfigTypes The config types to check.
* @param {ReadonlyArray<ExtraConfigType>} extraConfigTypes The config types to check.
* @param {string} namespacedBasePath The namespaced base path of the directory to which config base paths are relative.

@@ -659,3 +662,3 @@ * @param {PathImpl} path Path-handling implementation

* matcher.
* @param {Array<{ basePath?: string, ignores: Array<string|((string) => boolean)>}>} configs Configuration objects containing `ignores`.
* @param {Array<{ basePath?: string, ignores: FileMatcher[] }>} configs Configuration objects containing `ignores`.
* @param {string} filePath The unprocessed file path to check.

@@ -666,3 +669,3 @@ * @param {string} relativeFilePath The path of the file to check relative to the base path,

* that have `basePath` property.
* @param {string} [basePathData.basePath] Namespaced path to witch `relativeFilePath` is relative.
* @param {string} [basePathData.basePath] Namespaced path to which `relativeFilePath` is relative.
* @param {PathImpl} [basePathData.path] Path-handling implementation.

@@ -736,3 +739,3 @@ * @returns {boolean} True if the path should be ignored and false if not.

* using forward slash (`"/"`) as a separator.
* @param {Object} config The config object to check.
* @param {ConfigObject & { files: FilesMatcher[] }} config The config object to check.
* @returns {boolean} True if the file path is matched by the config,

@@ -800,3 +803,3 @@ * false if not.

* Ensures that config types are valid.
* @param {Array<string>} extraConfigTypes The config types to check.
* @param {ReadonlyArray<ExtraConfigType>} extraConfigTypes The config types to check.
* @returns {void}

@@ -806,6 +809,8 @@ * @throws {TypeError} When the config types array is invalid.

function assertExtraConfigTypes(extraConfigTypes) {
if (!Array.isArray(extraConfigTypes)) {
throw new TypeError("extraConfigTypes must be an array.");
}
if (extraConfigTypes.length > 2) {
throw new TypeError(
"configTypes must be an array with at most two items.",
);
throw new TypeError("extraConfigTypes must contain at most two items.");
}

@@ -816,3 +821,3 @@

throw new TypeError(
`Unexpected config type "${configType}" found. Expected one of: "object", "array", "function".`,
`Unexpected config type "${configType}" in extraConfigTypes. Expected one of: "array", "function".`,
);

@@ -888,5 +893,5 @@ }

* configs have already been normalized.
* @param {Object} [options.schema] The additional schema
* @param {ObjectDefinition} [options.schema] The additional schema
* definitions to use for the ConfigArray schema.
* @param {Array<string>} [options.extraConfigTypes] List of config types supported.
* @param {ReadonlyArray<ExtraConfigType>} [options.extraConfigTypes] List of config types supported.
* @throws {TypeError} When the `basePath` is not a non-empty string,

@@ -939,3 +944,3 @@ */

* The supported config types.
* @type {Array<string>}
* @type {ReadonlyArray<ExtraConfigType>}
*/

@@ -993,3 +998,3 @@ this.extraConfigTypes = [...extraConfigTypes];

* for a command line interface.
* @returns {Array<string|Function>} An array of matchers.
* @returns {Array<FilesMatcher>} An array of matchers.
*/

@@ -1030,3 +1035,3 @@ get files() {

* globbing operation to be faster.
* @returns {Object[]} An array of config objects representing global ignores.
* @returns {Array<{ basePath?: string, name?: string, ignores: FileMatcher[] }>} An array of config objects representing global ignores.
*/

@@ -1050,3 +1055,3 @@ get ignores() {

* We only count ignores if there are no other keys in the object.
* In this case, it acts list a globally ignored pattern. If there
* In this case, it acts like a globally ignored pattern. If there
* are additional keys, then ignores act like exclusions.

@@ -1053,0 +1058,0 @@ */

@@ -5,2 +5,16 @@ /**

*/
/**
* A file matcher used in `files` and `ignores`.
*/
export type FileMatcher = string | ((filePath: string) => boolean);
/**
* An entry in a config's `files` array.
*
* A subarray means all matchers must match.
*/
export type FilesMatcher = FileMatcher | FileMatcher[];
/**
* The config types allowed in the `extraConfigTypes` option.
*/
export type ExtraConfigType = "array" | "function";
export interface ConfigObject {

@@ -14,7 +28,7 @@ /**

*/
files?: string[];
files?: FilesMatcher[];
/**
* The files to exclude.
*/
ignores?: string[];
ignores?: FileMatcher[];
/**

@@ -21,0 +35,0 @@ * The name of the config object.

@@ -6,2 +6,19 @@ /**

/**
* A file matcher used in `files` and `ignores`.
*/
export type FileMatcher = string | ((filePath: string) => boolean);
/**
* An entry in a config's `files` array.
*
* A subarray means all matchers must match.
*/
export type FilesMatcher = FileMatcher | FileMatcher[];
/**
* The config types allowed in the `extraConfigTypes` option.
*/
export type ExtraConfigType = "array" | "function";
export interface ConfigObject {

@@ -16,3 +33,3 @@ /**

*/
files?: string[];
files?: FilesMatcher[];

@@ -22,3 +39,3 @@ /**

*/
ignores?: string[];
ignores?: FileMatcher[];

@@ -25,0 +42,0 @@ /**

{
"name": "@eslint/config-array",
"version": "0.23.2",
"version": "0.23.3",
"description": "General purpose glob-based configuration matching.",

@@ -54,5 +54,5 @@ "author": "Nicholas C. Zakas",

"dependencies": {
"@eslint/object-schema": "^3.0.2",
"@eslint/object-schema": "^3.0.3",
"debug": "^4.3.1",
"minimatch": "^10.2.1"
"minimatch": "^10.2.4"
},

@@ -59,0 +59,0 @@ "devDependencies": {

+40
-39

@@ -68,4 +68,9 @@ # Config Array

```js
import path from "node:path";
import { pathToFileURL } from "node:url";
import { ConfigArray } from "@eslint/config-array";
const configFilename = path.resolve(process.cwd(), "my.config.js");
const { default: rawConfigs } = await import(configFilename);
const { default: rawConfigs } = await import(pathToFileURL(configFilename));
const configs = new ConfigArray(rawConfigs, {

@@ -88,31 +93,28 @@ // the path to match filenames from

const configFilename = path.resolve(process.cwd(), "my.config.js");
const { default: rawConfigs } = await import(configFilename);
const { default: rawConfigs } = await import(pathToFileURL(configFilename));
const mySchema = {
// define the handler key in configs
handler: {
required: true,
merge(a, b) {
if (!b) return a;
if (!a) return b;
},
validate(value) {
if (typeof value !== "function") {
throw new TypeError("Function expected.");
}
}
}
// define the handler key in configs
handler: {
required: true,
merge(a, b) {
return b ?? a;
},
validate(value) {
if (typeof value !== "function") {
throw new TypeError("Function expected.");
}
},
},
};
const configs = new ConfigArray(rawConfigs, {
// the path to match filenames from
basePath: process.cwd(),
// the path to match filenames from
basePath: process.cwd(),
// additional item schemas in each config
schema: mySchema,
// additional item schemas in each config
schema: mySchema,
// additional config types supported (default: [])
extraConfigTypes: ["array", "function"];
// additional config types supported (default: [])
extraConfigTypes: ["array", "function"],
});

@@ -195,14 +197,13 @@ ```

export default [
// Always ignored
{
ignores: ["**/.git/**", "**/node_modules/**"],
},
// Always ignored
{
ignores: ["**/.git/**", "**/node_modules/**"]
},
// .eslintrc.js file is ignored only when .js file matches
{
files: ["**/*.js"],
ignores: [".eslintrc.js"]
handler: jsHandler
}
// .eslintrc.js file is ignored only when .js file matches
{
files: ["**/*.js"],
ignores: [".eslintrc.js"],
handler: jsHandler,
},
];

@@ -277,3 +278,3 @@ ```

```js
await configs.normalizeSync({
configs.normalizeSync({
name: "MyApp",

@@ -315,3 +316,3 @@ });

- **It's parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/a.js` is considered ignored.
- **Its parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/a.js` is considered ignored.
- **It has an ancestor directory that is ignored.** For example, if `foo` is in `ignores`, then `foo/baz/a.js` is considered ignored.

@@ -330,5 +331,5 @@ - **It matches an ignored file pattern.** For example, if `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.

- **It's parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/baz` is considered ignored.
- **Its parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/baz` is considered ignored.
- **It has an ancestor directory that is ignored.** For example, if `foo` is in `ignores`, then `foo/bar/baz/a.js` is considered ignored.
- **It matches and ignored file pattern.** For example, if `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
- **It matches an ignored file pattern.** For example, if `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
- **If it matches an entry in `files` and also in `ignores`.** For example, if `**/*.js` is in `files` and `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.

@@ -368,3 +369,3 @@ - **The file is outside the `basePath`.** If the `basePath` is `/usr/me`, then `/foo/a.js` is considered ignored.

<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a></p><h3>Gold Sponsors</h3>
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/d472863/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>

@@ -371,0 +372,0 @@ <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://opensource.sap.com"><img src="https://avatars.githubusercontent.com/u/2531208" alt="SAP" height="32"></a> <a href="https://www.crawljobs.com/"><img src="https://images.opencollective.com/crawljobs-poland/fa43a17/logo.png" alt="CrawlJobs" height="32"></a> <a href="https://depot.dev"><img src="https://images.opencollective.com/depot/39125a1/logo.png" alt="Depot" height="32"></a> <a href="https://www.n-ix.com/"><img src="https://images.opencollective.com/n-ix-ltd/575a7a5/logo.png" alt="N-iX Ltd" 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.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="TestMu AI Open Source Office (Formerly LambdaTest)" height="32"></a></p>