jsx_max_props_per_line

package
v0.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var JsxMaxPropsPerLineRule = rule.Rule{
	Name: "react/jsx-max-props-per-line",
	Run: func(ctx rule.RuleContext, options any) rule.RuleListeners {

		singleLimit := 0
		multiLimit := 0
		when := "always"
		maximumSet := false
		maximumIsObject := false

		optsMap := utils.GetOptionsMap(options)
		if optsMap != nil {
			if w, ok := optsMap["when"].(string); ok {
				when = w
			}
			if maxVal, ok := optsMap["maximum"]; ok {
				maximumSet = true
				switch v := maxVal.(type) {
				case float64:
					singleLimit = int(v)
					multiLimit = int(v)
				case map[string]interface{}:
					maximumIsObject = true
					if s, ok := v["single"].(float64); ok {
						singleLimit = int(s)
					}
					if m, ok := v["multi"].(float64); ok {
						multiLimit = int(m)
					}
				}
			}
		}

		if !maximumSet {
			singleLimit = 1
			multiLimit = 1
		}

		if !maximumIsObject && when == "multiline" {
			singleLimit = 0
		}

		check := func(node *ast.Node) {
			var props []*ast.Node

			switch node.Kind {
			case ast.KindJsxOpeningElement:
				attrs := node.AsJsxOpeningElement().Attributes.AsJsxAttributes()
				if attrs.Properties != nil {
					props = attrs.Properties.Nodes
				}
			case ast.KindJsxSelfClosingElement:
				attrs := node.AsJsxSelfClosingElement().Attributes.AsJsxAttributes()
				if attrs.Properties != nil {
					props = attrs.Properties.Nodes
				}
			}

			if len(props) == 0 {
				return
			}

			lineMap := ctx.SourceFile.ECMALineMap()

			openingTrimmed := utils.TrimNodeTextRange(ctx.SourceFile, node)
			firstLine := scanner.ComputeLineOfPosition(lineMap, openingTrimmed.Pos())
			lastLine := scanner.ComputeLineOfPosition(lineMap, openingTrimmed.End())
			isSingleLine := firstLine == lastLine

			var limit int
			if isSingleLine {
				limit = singleLimit
			} else {
				limit = multiLimit
			}

			if limit == 0 {
				return
			}

			if when == "multiline" && !maximumIsObject && isSingleLine {
				return
			}

			// Group props by line — ESLint chains by checking if the previous prop's
			// END line equals the current prop's START line (handles multi-line props).
			type lineGroup struct {
				endLine int
				props   []*ast.Node
			}

			var groups []lineGroup
			for _, prop := range props {
				propTrimmed := utils.TrimNodeTextRange(ctx.SourceFile, prop)
				propStartLine := scanner.ComputeLineOfPosition(lineMap, propTrimmed.Pos())
				propEndLine := scanner.ComputeLineOfPosition(lineMap, propTrimmed.End())
				if len(groups) == 0 || groups[len(groups)-1].endLine != propStartLine {
					groups = append(groups, lineGroup{endLine: propEndLine, props: []*ast.Node{prop}})
				} else {
					groups[len(groups)-1].endLine = propEndLine
					groups[len(groups)-1].props = append(groups[len(groups)-1].props, prop)
				}
			}

			text := ctx.SourceFile.Text()

			for _, group := range groups {
				if len(group.props) > limit {
					prop := group.props[limit]
					propName := getPropName(prop)
					propTrimmed := utils.TrimNodeTextRange(ctx.SourceFile, prop)
					propStart := propTrimmed.Pos()
					wsStart := propStart
					for wsStart > 0 && (text[wsStart-1] == ' ' || text[wsStart-1] == '\t') {
						wsStart--
					}
					ctx.ReportNodeWithFixes(prop, rule.RuleMessage{
						Id:          "newLine",
						Description: fmt.Sprintf("Prop `%s` must be placed on a new line", propName),
					}, rule.RuleFix{
						Text:  "\n",
						Range: core.NewTextRange(wsStart, propStart),
					})
				}
			}
		}

		return rule.RuleListeners{
			ast.KindJsxOpeningElement:     check,
			ast.KindJsxSelfClosingElement: check,
		}
	},
}

JsxMaxPropsPerLineRule limits the maximum number of props on a single line in JSX.

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL