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

[Bug]: Wrong definition. jsx-closing-bracket-location #3655

Open
2 tasks done
CzarOfScripts opened this issue Nov 20, 2023 · 9 comments
Open
2 tasks done

[Bug]: Wrong definition. jsx-closing-bracket-location #3655

CzarOfScripts opened this issue Nov 20, 2023 · 9 comments
Labels

Comments

@CzarOfScripts
Copy link

CzarOfScripts commented Nov 20, 2023

Is there an existing issue for this?

  • I have searched the existing issues and my issue is unique
  • My issue appears in the command-line and not only in the text editor

Description Overview

I want to use the line-aligned value, but I don't think it works correctly if I have a props that has a hyphenated object.

Here's an example where I don't expect to see any errors:

<Box sx={{
	position: "relative",
	maxWidth: "720px",
	width: "100%",
	backgroundColor: "#26216d"
}}>
	{/* Content */}
</Box>

or

<Box sx={{
	position: "relative",
	maxWidth: "720px",
	width: "100%",
	backgroundColor: "#26216d"
}} />

I think it's because of multiline in props that I'm getting the error.

"react/jsx-closing-bracket-location": [ "error", { "nonEmpty": "line-aligned", "selfClosing": "line-aligned" } ]

Expected Behavior

I would like the code I have provided to work perfectly, for I believe this is the right way to go.

<Box sx={{
	position: "relative",
	maxWidth: "720px",
	width: "100%",
	backgroundColor: "#26216d"
}}>
	{/* Content */}
</Box>

or

<Box sx={{
	position: "relative",
	maxWidth: "720px",
	width: "100%",
	backgroundColor: "#26216d"
}} />

eslint-plugin-react version

^7.33.2

eslint version

^8.54.0

node version

v18.12.1

@ljharb
Copy link
Member

ljharb commented Nov 20, 2023

The rule is expecting this, i suspect:

<Box
  sx={{
  }}
/>

the tag name and prop name shouldn’t be on the same line, if the prop is spread across multiple lines.

@CzarOfScripts
Copy link
Author

@ljharb, I understand what it expects, but I don't think it's the right option. Why should I carry over if I only have one attribute, even though it's multi-line? I think there should be some kind of customization.

@ljharb
Copy link
Member

ljharb commented Nov 20, 2023

Because you have more than zero attributes. The premise (also supported by the Airbnb styleguide) is that if an entire thing - in this case, a jsx element - isn’t contained within a single line, then each conceptual thing should be on its own line by itself.

We could allow the customization you want via an option, but that’s a lot of extra complexity for something that I’m convinced makes for less readable and deterministic code.

@CzarOfScripts
Copy link
Author

My personal opinion: this variant looks much worse, because it takes up a lot of space. My variant is more compact and readable. If there is no such variant, it is very sad and it looks like I will have to give up this rule altogether, which I would not like.

@ljharb
Copy link
Member

ljharb commented Nov 20, 2023

Compactness can often hurt readability.

@CzarOfScripts
Copy link
Author

Ok, I've decided to try to go with the current format after all. But then how do I automatically move the props to a new line? Right now I get the following:

<Box sx={{
  minHeight: "100vh",
  background: `url(${ IMGBackground }) center center/cover`,
  display: "flex",
  flexDirection: "column",
  
  "@supports (min-height: 100dvh)":
  {
	  minHeight: "100dvh"
  }
}}
>
  <Component />
</Box>

@ljharb
Copy link
Member

ljharb commented Jan 10, 2024

What I'd expect is this:

<Box
  sx={{
    minHeight: "100vh",
    background: `url(${ IMGBackground }) center center/cover`,
    display: "flex",
    flexDirection: "column",
  
    "@supports (min-height: 100dvh)": {
      minHeight: "100dvh"
    }
  }}
>
  <Component />
</Box>

If you start with the airbnb config, it should be roughly corrected to this?

@CzarOfScripts
Copy link
Author

Well, if you're judging by jsx, yes. I can provide my config.

{
	"plugins": [ "react", "@typescript-eslint", "react-hooks" ],
	"parser": "@typescript-eslint/parser",
	"parserOptions": {
		"project": "./tsconfig.json"
	},
	"settings": {
		"react": { "version": "detect" }
	},
	"rules": {
		"no-restricted-imports": [
			"error",
			{
				"paths": [
					{
						"name": "react-i18next",
						"importNames": [
							"useTranslation"
						],
						"message": "Please use useTranslation from next-i18next instead."
					}
				]
			}
		],
		"array-bracket-newline": [ "error", "consistent" ],
		"array-bracket-spacing": [ "error", "always" ],
		"array-element-newline": [ "error", "consistent" ],
		"arrow-spacing": [ "error", { "before": true, "after": true } ],
		"block-spacing": [ "error", "always" ],
		"brace-style": [ "error", "allman", { "allowSingleLine": true } ],
		"comma-dangle": [ "error", "never" ],
		"comma-spacing": [ "error", { "before": false, "after": true } ],
		"comma-style": [ "error", "last" ],
		"computed-property-spacing": [ "error", "always" ],
		"keyword-spacing": [ "error", { "before": true, "after": true } ],
		"no-extra-semi": "error",
		"object-curly-spacing": [ "error", "always" ],
		"object-curly-newline": [ "error", { "consistent": true, "multiline": true } ],
		"object-property-newline": [ "error", { "allowAllPropertiesOnSameLine": true } ],
		"quotes": [ "error", "double", { "avoidEscape": true } ],
		"semi": "error",
		"semi-spacing": [ "error", { "before": false, "after": true } ],
		"space-before-blocks": "error",
		"space-before-function-paren": [ "error", { "asyncArrow": "always", "anonymous": "always", "named": "never" } ],
		"template-curly-spacing": [ "error", "always" ],
		"template-tag-spacing": [ "error", "never" ],
		"space-in-parens": [ "error", "never" ],
		"space-infix-ops": [ "error", { "int32Hint": false } ],
		"space-unary-ops": [ "error", { "words": true, "nonwords": false } ],
		"switch-colon-spacing": [ "error", { "after": true, "before": false } ],
		"dot-location": [ "error", "property" ],
		"dot-notation": "off",
		"eol-last": [ "error", "always" ],
		"no-multiple-empty-lines": [ "error", { "max": 1, "maxEOF": 0, "maxBOF": 0 } ],
		"no-trailing-spaces": "error",
		"func-call-spacing": [ "error", "never" ],
		"function-call-argument-newline": [ "error", "consistent" ],
		"function-paren-newline": [ "error", "multiline-arguments" ],
		"implicit-arrow-linebreak": [ "error", "beside" ],
		"indent": [ "error", "tab", { "SwitchCase": 1, "MemberExpression": 1 } ],
		"jsx-quotes": [ "error", "prefer-double" ],
		"key-spacing": [ "error", { "beforeColon": false, "afterColon": true } ],
		"padding-line-between-statements": [
			"error",
			{ "blankLine": "always", "prev": [ "import", "cjs-import", "function", "block-like", "multiline-const", "multiline-let", "multiline-var" ], "next": "*" },
			{ "blankLine": "any", "prev": [ "import", "cjs-import" ], "next": [ "import", "cjs-import" ] },
			{ "blankLine": "always", "prev": [ "const", "let", "var" ], "next": "*" },
			{ "blankLine": "any", "prev": [ "const", "let", "var" ], "next": [ "const", "let", "var", "if" ] },
			{ "blankLine": "always", "prev": "*", "next": "return" }
		],
		"max-len": [
			"error",
			{
				"code": 140,
				"tabWidth": 3,
				"ignoreUrls": true,
				"ignoreStrings": true,
				"ignoreTemplateLiterals": true,
				"ignoreRegExpLiterals": true,
				"ignoreComments": true,
				"ignoreTrailingComments": true
			}
		],
		"multiline-ternary": [ "error", "always-multiline" ],
		"new-parens": "error",
		"newline-per-chained-call": [ "error", { "ignoreChainWithDepth": 3 } ],
		"no-mixed-spaces-and-tabs": [ "error", "smart-tabs" ],
		"no-multi-spaces": "error",
		"no-whitespace-before-property": "error",
		"quote-props": [ "error", "as-needed" ],
		"rest-spread-spacing": [ "error", "never" ],
		"vars-on-top": "error",
		"no-unneeded-ternary": "error",
		"no-console": [ "error", { "allow": [ "warn", "error", "debug", "info" ] } ],
		"no-else-return": "error",
		"func-style": [ "error", "declaration" ],
		"default-param-last": "off",
		"use-isnan": "error",
		// React
		"react/destructuring-assignment": [ "error", "always" ],
		"react/function-component-definition": [
			"error",
			{ "namedComponents": "function-declaration", "unnamedComponents": "arrow-function" }
		],
		"react/hook-use-state": [ "off", { "allowDestructuredState": true } ],
		"react/jsx-boolean-value": [ "error", "never" ],
		"react/jsx-closing-bracket-location": [ "error", { "nonEmpty": "line-aligned", "selfClosing": "line-aligned" } ],
		"react/jsx-closing-tag-location": [ "error" ],
		"react/jsx-curly-brace-presence": [ "error", { "props": "never", "children": "never", "propElementValues": "always" } ],
		"react/jsx-equals-spacing": [ "error", "never" ],
		"react/jsx-filename-extension": [ "error", { "extensions": [ ".jsx", ".tsx" ] } ],
		"react/jsx-fragments": [ "error", "syntax" ],
		"react/jsx-first-prop-new-line": [ "error", "multiline-multiprop" ],
		"react/jsx-indent": [ "error", "tab", { "indentLogicalExpressions": true, "checkAttributes": true } ],
		"react/jsx-indent-props": [ "error", "tab" ],
		"react/jsx-key": [ "off" ],
		"react/jsx-max-props-per-line": [ "error", { "maximum": { "single": 5, "multi": 1 } } ],
		"react/jsx-no-constructed-context-values": [ "error" ],
		"react/jsx-no-duplicate-props": [ "error" ],
		"react/jsx-no-leaked-render": [ "error" ],
		"react/jsx-no-useless-fragment": [ "error", { "allowExpressions": true } ],
		"react/jsx-pascal-case": [ "error", { "allowNamespace": true } ],
		"react/jsx-props-no-multi-spaces": [ "error" ],
		"react/jsx-tag-spacing": [
			"error",
			{
				"closingSlash": "never",
				"beforeSelfClosing": "always",
				"afterOpening": "never",
				"beforeClosing": "never"
			}
		],
		"react/jsx-wrap-multilines": [
			"error",
			{
				"declaration": "parens",
				"assignment": "parens",
				"return": "parens",
				"arrow": "parens-new-line",
				"condition": "ignore",
				"logical": "ignore",
				"prop": "ignore"
			}
		],
		"react/self-closing-comp": [
			"error",
			{
				"component": true,
				"html": true
			}
		],
		"react/style-prop-object": [ "error" ],
		// Typescript
		"@typescript-eslint/adjacent-overload-signatures": "error",
		"@typescript-eslint/await-thenable": "error",
		"@typescript-eslint/consistent-generic-constructors": [ "error", "constructor" ],
		"@typescript-eslint/consistent-indexed-object-style": [ "error", "record" ],
		"@typescript-eslint/default-param-last": "error",
		"@typescript-eslint/dot-notation": "error",
		"@typescript-eslint/explicit-member-accessibility": [ "error", { "accessibility": "no-public" } ],
		"@typescript-eslint/member-delimiter-style": [ "error", { "singleline": { "requireLast": true } } ],
		"@typescript-eslint/method-signature-style": [ "error", "method" ],
		"@typescript-eslint/no-base-to-string": "error",
		"@typescript-eslint/no-confusing-non-null-assertion": "error",
		"@typescript-eslint/no-duplicate-enum-values": "error",
		"@typescript-eslint/no-duplicate-type-constituents": "error",
		"@typescript-eslint/no-empty-function": "error",
		"@typescript-eslint/no-empty-interface": [ "off", { "allowSingleExtends": true } ],
		"@typescript-eslint/no-for-in-array": "error",
		"@typescript-eslint/prefer-for-of": "error",
		"@typescript-eslint/prefer-optional-chain": "error",
		"@typescript-eslint/prefer-reduce-type-parameter": "error",
		"@typescript-eslint/prefer-string-starts-ends-with": "error",
		"@typescript-eslint/require-array-sort-compare": "error",
		"@typescript-eslint/type-annotation-spacing": [
			"error",
			{
				"before": false,
				"after": true,
				"overrides": { "arrow": { "before": true, "after": true } }
			}
		]
	}
}

@ljharb
Copy link
Member

ljharb commented May 31, 2024

@CzarOfScripts sorry for the long delay. if you autofix with the full airbnb config, what code are you left with that still requires manual fixing, and what are the errors?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants