@eslint/eslintrc
Advanced tools
| /** | ||
| * @fileoverview Stub eslint:all config | ||
| * @author Nicholas C. Zakas | ||
| */ | ||
| "use strict"; | ||
| module.exports = { | ||
| settings: { | ||
| "eslint:all": true | ||
| } | ||
| }; |
| /** | ||
| * @fileoverview Stub eslint:recommended config | ||
| * @author Nicholas C. Zakas | ||
| */ | ||
| "use strict"; | ||
| module.exports = { | ||
| settings: { | ||
| "eslint:recommended": true | ||
| } | ||
| }; |
| /** | ||
| * @fileoverview Compatibility class for flat config. | ||
| * @author Nicholas C. Zakas | ||
| */ | ||
| "use strict"; | ||
| //----------------------------------------------------------------------------- | ||
| // Requirements | ||
| //----------------------------------------------------------------------------- | ||
| const path = require("path"); | ||
| const environments = require("../conf/environments"); | ||
| const createDebug = require("debug"); | ||
| const { ConfigArrayFactory } = require("./config-array-factory"); | ||
| //----------------------------------------------------------------------------- | ||
| // Helpers | ||
| //----------------------------------------------------------------------------- | ||
| /** @typedef {import("../../shared/types").Environment} Environment */ | ||
| /** @typedef {import("../../shared/types").Processor} Processor */ | ||
| const debug = createDebug("eslintrc:flat-compat"); | ||
| const cafactory = Symbol("cafactory"); | ||
| /** | ||
| * Translates an ESLintRC-style config object into a flag-config-style config | ||
| * object. | ||
| * @param {Object} eslintrcConfig An ESLintRC-style config object. | ||
| * @param {Object} options Options to help translate the config. | ||
| * @param {string} options.resolveConfigRelativeTo To the directory to resolve | ||
| * configs from. | ||
| * @param {string} options.resolvePluginsRelativeTo The directory to resolve | ||
| * plugins from. | ||
| * @param {ReadOnlyMap<string,Environment>} options.pluginEnvironments A map of plugin environment | ||
| * names to objects. | ||
| * @param {ReadOnlyMap<string,Processor>} options.pluginProcessors A map of plugin processor | ||
| * names to objects. | ||
| * @returns {Object} A flag-config-style config object. | ||
| */ | ||
| function translateESLintRC(eslintrcConfig, { | ||
| resolveConfigRelativeTo, | ||
| resolvePluginsRelativeTo, | ||
| pluginEnvironments, | ||
| pluginProcessors | ||
| }) { | ||
| const flatConfig = {}; | ||
| const configs = []; | ||
| const languageOptions = {}; | ||
| const linterOptions = {}; | ||
| const keysToCopy = ["settings", "rules", "processor"]; | ||
| const languageOptionsKeysToCopy = ["globals", "parser", "parserOptions"]; | ||
| const linterOptionsKeysToCopy = ["noInlineConfig", "reportUnusedDisableDirectives"]; | ||
| // check for special settings for eslint:all and eslint:recommended: | ||
| if (eslintrcConfig.settings) { | ||
| if (eslintrcConfig.settings["eslint:all"] === true) { | ||
| return ["eslint:all"]; | ||
| } | ||
| if (eslintrcConfig.settings["eslint:recommended"] === true) { | ||
| return ["eslint:recommended"]; | ||
| } | ||
| } | ||
| // copy over simple translations | ||
| for (const key of keysToCopy) { | ||
| if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") { | ||
| flatConfig[key] = eslintrcConfig[key]; | ||
| } | ||
| } | ||
| // copy over languageOptions | ||
| for (const key of languageOptionsKeysToCopy) { | ||
| if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") { | ||
| // create the languageOptions key in the flat config | ||
| flatConfig.languageOptions = languageOptions; | ||
| if (key === "parser") { | ||
| debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`); | ||
| if (eslintrcConfig[key].error) { | ||
| throw eslintrcConfig[key].error; | ||
| } | ||
| languageOptions[key] = eslintrcConfig[key].definition; | ||
| continue; | ||
| } | ||
| // clone any object values that are in the eslintrc config | ||
| if (eslintrcConfig[key] && typeof eslintrcConfig[key] === "object") { | ||
| languageOptions[key] = { | ||
| ...eslintrcConfig[key] | ||
| }; | ||
| } else { | ||
| languageOptions[key] = eslintrcConfig[key]; | ||
| } | ||
| } | ||
| } | ||
| // copy over linterOptions | ||
| for (const key of linterOptionsKeysToCopy) { | ||
| if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") { | ||
| flatConfig.linterOptions = linterOptions; | ||
| linterOptions[key] = eslintrcConfig[key]; | ||
| } | ||
| } | ||
| // move ecmaVersion a level up | ||
| if (languageOptions.parserOptions) { | ||
| if ("ecmaVersion" in languageOptions.parserOptions) { | ||
| languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion; | ||
| delete languageOptions.parserOptions.ecmaVersion; | ||
| } | ||
| if ("sourceType" in languageOptions.parserOptions) { | ||
| languageOptions.sourceType = languageOptions.parserOptions.sourceType; | ||
| delete languageOptions.parserOptions.sourceType; | ||
| } | ||
| // check to see if we even need parserOptions anymore and remove it if not | ||
| if (Object.keys(languageOptions.parserOptions).length === 0) { | ||
| delete languageOptions.parserOptions; | ||
| } | ||
| } | ||
| // overrides | ||
| if (eslintrcConfig.criteria) { | ||
| flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)]; | ||
| } | ||
| // translate plugins | ||
| if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === "object") { | ||
| debug(`Translating plugins: ${eslintrcConfig.plugins}`); | ||
| flatConfig.plugins = {}; | ||
| for (const pluginName of Object.keys(eslintrcConfig.plugins)) { | ||
| debug(`Translating plugin: ${pluginName}`); | ||
| debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`); | ||
| const { definition: plugin, error } = eslintrcConfig.plugins[pluginName]; | ||
| if (error) { | ||
| throw error; | ||
| } | ||
| flatConfig.plugins[pluginName] = plugin; | ||
| // create a config for any processors | ||
| if (plugin.processors) { | ||
| for (const processorName of Object.keys(plugin.processors)) { | ||
| if (processorName.startsWith(".")) { | ||
| debug(`Assigning processor: ${pluginName}/${processorName}`); | ||
| configs.unshift({ | ||
| files: [`**/*${processorName}`], | ||
| processor: pluginProcessors.get(`${pluginName}/${processorName}`) | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // translate env - must come after plugins | ||
| if (eslintrcConfig.env && typeof eslintrcConfig.env === "object") { | ||
| for (const envName of Object.keys(eslintrcConfig.env)) { | ||
| // only add environments that are true | ||
| if (eslintrcConfig.env[envName]) { | ||
| debug(`Translating environment: ${envName}`); | ||
| if (environments.has(envName)) { | ||
| // built-in environments should be defined first | ||
| configs.unshift(...translateESLintRC(environments.get(envName), { | ||
| resolveConfigRelativeTo, | ||
| resolvePluginsRelativeTo | ||
| })); | ||
| } else if (pluginEnvironments.has(envName)) { | ||
| // if the environment comes from a plugin, it should come after the plugin config | ||
| configs.push(...translateESLintRC(pluginEnvironments.get(envName), { | ||
| resolveConfigRelativeTo, | ||
| resolvePluginsRelativeTo | ||
| })); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // only add if there are actually keys in the config | ||
| if (Object.keys(flatConfig).length > 0) { | ||
| configs.push(flatConfig); | ||
| } | ||
| return configs; | ||
| } | ||
| //----------------------------------------------------------------------------- | ||
| // Exports | ||
| //----------------------------------------------------------------------------- | ||
| /** | ||
| * A compatibility class for working with configs. | ||
| */ | ||
| class FlatCompat { | ||
| constructor({ | ||
| baseDirectory = process.cwd(), | ||
| resolvePluginsRelativeTo = baseDirectory | ||
| } = {}) { | ||
| this.baseDirectory = baseDirectory; | ||
| this.resolvePluginsRelativeTo = resolvePluginsRelativeTo; | ||
| this[cafactory] = new ConfigArrayFactory({ | ||
| cwd: baseDirectory, | ||
| resolvePluginsRelativeTo, | ||
| eslintAllPath: path.resolve(__dirname, "../conf/eslint-all.js"), | ||
| eslintRecommendedPath: path.resolve(__dirname, "../conf/eslint-recommended.js") | ||
| }); | ||
| } | ||
| /** | ||
| * Translates an ESLintRC-style config into a flag-config-style config. | ||
| * @param {Object} eslintrcConfig The ESLintRC-style config object. | ||
| * @returns {Object} A flag-config-style config object. | ||
| */ | ||
| config(eslintrcConfig) { | ||
| const eslintrcArray = this[cafactory].create(eslintrcConfig, { | ||
| basePath: this.baseDirectory | ||
| }); | ||
| const flatArray = []; | ||
| let hasIgnorePatterns = false; | ||
| eslintrcArray.forEach(configData => { | ||
| if (configData.type === "config") { | ||
| hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern; | ||
| flatArray.push(...translateESLintRC(configData, { | ||
| resolveConfigRelativeTo: path.join(this.baseDirectory, "__placeholder.js"), | ||
| resolvePluginsRelativeTo: path.join(this.resolvePluginsRelativeTo, "__placeholder.js"), | ||
| pluginEnvironments: eslintrcArray.pluginEnvironments, | ||
| pluginProcessors: eslintrcArray.pluginProcessors | ||
| })); | ||
| } | ||
| }); | ||
| // combine ignorePatterns to emulate ESLintRC behavior better | ||
| if (hasIgnorePatterns) { | ||
| flatArray.unshift({ | ||
| ignores: [filePath => { | ||
| // Compute the final config for this file. | ||
| // This filters config array elements by `files`/`excludedFiles` then merges the elements. | ||
| const finalConfig = eslintrcArray.extractConfig(filePath); | ||
| // Test the `ignorePattern` properties of the final config. | ||
| return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath); | ||
| }] | ||
| }); | ||
| } | ||
| return flatArray; | ||
| } | ||
| /** | ||
| * Translates the `env` section of an ESLintRC-style config. | ||
| * @param {Object} envConfig The `env` section of an ESLintRC config. | ||
| * @returns {Object} A flag-config object representing the environments. | ||
| */ | ||
| env(envConfig) { | ||
| return this.config({ | ||
| env: envConfig | ||
| }); | ||
| } | ||
| /** | ||
| * Translates the `extends` section of an ESLintRC-style config. | ||
| * @param {...string} configsToExtend The names of the configs to load. | ||
| * @returns {Object} A flag-config object representing the config. | ||
| */ | ||
| extends(...configsToExtend) { | ||
| return this.config({ | ||
| extends: configsToExtend | ||
| }); | ||
| } | ||
| /** | ||
| * Translates the `plugins` section of an ESLintRC-style config. | ||
| * @param {...string} plugins The names of the plugins to load. | ||
| * @returns {Object} A flag-config object representing the plugins. | ||
| */ | ||
| plugins(...plugins) { | ||
| return this.config({ | ||
| plugins | ||
| }); | ||
| } | ||
| } | ||
| exports.FlatCompat = FlatCompat; |
+6
-0
@@ -0,1 +1,7 @@ | ||
| v0.4.0 - February 27, 2021 | ||
| * [`d9a527b`](https://github.com/eslint/eslintrc/commit/d9a527bdb16af46a28d37fa9022131149970a438) New: Implement DotCompat class (#20) (Nicholas C. Zakas) | ||
| * [`dac76c0`](https://github.com/eslint/eslintrc/commit/dac76c035a9ab9d315050f688867373966aab288) Chore: Replace usage of lodash with cache set (#29) (Tim van der Lippe) | ||
| * [`3ae2d77`](https://github.com/eslint/eslintrc/commit/3ae2d770cb810c026de817e6861e25dac111da9f) Update: add AggregateError global to es2021 environment (#28) (Milos Djermanovic) | ||
| v0.3.0 - January 15, 2021 | ||
@@ -2,0 +8,0 @@ |
@@ -48,2 +48,3 @@ /** | ||
| const newGlobals2021 = { | ||
| AggregateError: false, | ||
| FinalizationRegistry: false, | ||
@@ -50,0 +51,0 @@ WeakRef: false |
+4
-1
@@ -26,2 +26,3 @@ /** | ||
| const naming = require("./shared/naming"); | ||
| const { FlatCompat } = require("./flat-compat"); | ||
@@ -50,4 +51,6 @@ //----------------------------------------------------------------------------- | ||
| naming | ||
| } | ||
| }, | ||
| FlatCompat | ||
| }; |
@@ -12,3 +12,2 @@ /** | ||
| const path = require("path"); | ||
| const lodash = require("lodash"); | ||
@@ -32,2 +31,4 @@ //------------------------------------------------------------------------------ | ||
| const sourceFileErrorCache = new Set(); | ||
| /** | ||
@@ -41,3 +42,10 @@ * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted | ||
| */ | ||
| const emitDeprecationWarning = lodash.memoize((source, errorCode) => { | ||
| function emitDeprecationWarning(source, errorCode) { | ||
| const cacheKey = JSON.stringify({ source, errorCode }); | ||
| if (sourceFileErrorCache.has(cacheKey)) { | ||
| return; | ||
| } | ||
| sourceFileErrorCache.add(cacheKey); | ||
| const rel = path.relative(process.cwd(), source); | ||
@@ -51,3 +59,3 @@ const message = deprecationWarningMessages[errorCode]; | ||
| ); | ||
| }, (...args) => JSON.stringify(args)); | ||
| } | ||
@@ -54,0 +62,0 @@ //------------------------------------------------------------------------------ |
+2
-2
| { | ||
| "name": "@eslint/eslintrc", | ||
| "version": "0.3.0", | ||
| "version": "0.4.0", | ||
| "description": "The legacy ESLintRC config file format for ESLint", | ||
@@ -44,2 +44,3 @@ "main": "lib/index.js", | ||
| "mocha": "^8.1.1", | ||
| "shelljs": "^0.8.4", | ||
| "sinon": "^9.2.0", | ||
@@ -56,3 +57,2 @@ "temp-dir": "^2.0.0" | ||
| "js-yaml": "^3.13.1", | ||
| "lodash": "^4.17.20", | ||
| "minimatch": "^3.0.4", | ||
@@ -59,0 +59,0 @@ "strip-json-comments": "^3.1.1" |
+41
-1
@@ -7,3 +7,3 @@ # ESLintRC Library | ||
| ## Usage | ||
| ## Installation | ||
@@ -20,4 +20,44 @@ You can install the package as follows: | ||
| ## Future Usage | ||
| **Note:** This package is not intended for public use at this time. The following is an example of how it will be used in the future. | ||
| The primary class in this package is `FlatCompat`, which is a utility to translate ESLintRC-style configs into flat configs. Here's how you use it inside of your `eslint.config.js` file: | ||
| ```js | ||
| import { FlatCompat } from "@eslint/eslintrc"; | ||
| const compat = new FlatCompat(); | ||
| export default [ | ||
| // mimic ESLintRC-style extends | ||
| compat.extends("standard", "example"), | ||
| // mimic environments | ||
| compat.env({ | ||
| es2020: true, | ||
| node: true | ||
| }), | ||
| // mimic plugins | ||
| compat.plugins("airbnb", "react"), | ||
| // translate an entire config | ||
| compat.config({ | ||
| plugins: ["airbnb", "react"], | ||
| extends: "standard", | ||
| env: { | ||
| es2020: true, | ||
| node: true | ||
| }, | ||
| rules: { | ||
| semi: "error" | ||
| } | ||
| }) | ||
| ]; | ||
| ``` | ||
| ## License | ||
| MIT License |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
156373
9.09%9
-10%25
13.64%3813
7.96%62
181.82%11
10%- Removed
- Removed