Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support JS objects for extends config option #6952

Closed
ybiquitous opened this issue Jun 22, 2023 · 0 comments · Fixed by #6998
Closed

Add support JS objects for extends config option #6952

ybiquitous opened this issue Jun 22, 2023 · 0 comments · Fixed by #6998
Labels
status: wip is being worked on by someone type: enhancement a new feature that isn't related to rules

Comments

@ybiquitous
Copy link
Member

What is the problem you're trying to solve?

First, assume that there is a pure ESM package for a sharable config named foo-config:

foo-config/package.json:

{
  "name": "foo-config",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js"
}

foo-config/index.js:

export default {
	rules: {
		'color-no-invalid-hex': true,
	},
};

Next, consider a case using foo-config via npm:

package.json:

{
  "dependencies": {
    "foo-config": "^1.0.0",
    "stylelint": "^15.8.0"
  }
}

.stylelintrc.mjs:

import foo from 'foo-config';

export default {
	// Not working => Error [ERR_REQUIRE_ESM]: require() of ES Module ...
	extends: 'foo-config',

	// Still not working => TypeError: Expected `moduleId` to be of type `string`, got `object`
	extends: foo,
};

Running stylelint like this raises the errors above:

echo 'a { color: #f4 }' | npx stylelint --stdin

This means that Stylelint cannot use a pure ESM sharable config with the extends option.

Related: #5291

What solution would you like to see?

I expect Stylelint to work even when using JS objects with extends instead of strings (e.g., package name or path). For example:

$ echo 'a { color: #f4 }' | npx stylelint --stdin

<input css qXAh0i>
 1:12  ✖  Unexpected invalid hex color "#f4"  color-no-invalid-hex

1 problem (1 error, 0 warnings)

I find it works by applying the following patch:

--- a/lib/augmentConfig.js
+++ b/lib/augmentConfig.js
@@ -178,7 +178,13 @@ async function extendConfig(stylelint, config, configDir, rootConfigDir, filePat
 	let resultConfig = originalWithoutExtends;
 
 	for (const extendLookup of normalizedExtends) {
-		const extendResult = await loadExtendedConfig(stylelint, configDir, extendLookup);
+		let extendResult;
+
+		if (typeof extendLookup === 'string') {
+			extendResult = await loadExtendedConfig(stylelint, configDir, extendLookup);
+		} else if (typeof extendLookup === 'object' && extendLookup !== null) {
+			extendResult = { config: extendLookup };
+		}
 
 		if (extendResult) {
 			let extendResultConfig = extendResult.config;

This patch simply uses JS objects if they are passed.

What do you think about this idea? Is there some pitfall?


For your information, I refer to the current spec of extends:

The value of `"extends"` is a "locater" (or an array of "locaters") that is ultimately `require()`d. It can fit whatever format works with Node's `require.resolve()` algorithm. That means a "locater" can be:
- the name of a module in `node_modules` (e.g. `stylelint-config-standard`; that module's `main` file must be a valid JSON configuration)
- an absolute path to a file (which makes sense if you're creating a JS object in a Node.js context and passing it in) with a `.js` or `.json` extension.
- a relative path to a file with a `.js` or `.json` extension, relative to the referencing configuration (e.g. if configA has `extends: "../configB"`, we'll look for `configB` relative to configA).

@ybiquitous ybiquitous added the status: needs discussion triage needs further discussion label Jun 22, 2023
@jeddy3 jeddy3 added status: ready to implement is ready to be worked on by someone type: enhancement a new feature that isn't related to rules and removed status: needs discussion triage needs further discussion labels Jun 24, 2023
@ybiquitous ybiquitous added status: wip is being worked on by someone and removed status: ready to implement is ready to be worked on by someone labels Jul 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: wip is being worked on by someone type: enhancement a new feature that isn't related to rules
Development

Successfully merging a pull request may close this issue.

2 participants