Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var JsxIndentPropsRule = rule.Rule{ Name: "react/jsx-indent-props", Run: func(ctx rule.RuleContext, options any) rule.RuleListeners { indentType, indentSize, indentChar, indentIsFirst, ignoreTernaryOperator := parseOptions(options) text := ctx.SourceFile.Text() lineMap := ctx.SourceFile.ECMALineMap() firstNonWhitespaceCharOnLine := func(pos int) byte { start := reactutil.IndentLineStart(lineMap, pos) for i := start; i < len(text); i++ { c := text[i] if c == ' ' || c == '\t' { continue } if c == '\n' || c == '\r' { return 0 } return c } return 0 } firstLineContainsBracket := func(node *ast.Node) bool { trimmed := utils.TrimNodeTextRange(ctx.SourceFile, node) lineStart := reactutil.IndentLineStart(lineMap, trimmed.Pos()) end := trimmed.End() for i := lineStart; i < end && i < len(text); i++ { c := text[i] if c == '\n' { break } if c == '<' { return true } } return false } check := func(node *ast.Node) { var props []*ast.Node switch node.Kind { case ast.KindJsxOpeningElement: opening := node.AsJsxOpeningElement() if opening.Attributes != nil { attrs := opening.Attributes.AsJsxAttributes() if attrs != nil && attrs.Properties != nil { props = attrs.Properties.Nodes } } case ast.KindJsxSelfClosingElement: self := node.AsJsxSelfClosingElement() if self.Attributes != nil { attrs := self.Attributes.AsJsxAttributes() if attrs != nil && attrs.Properties != nil { props = attrs.Properties.Nodes } } } if len(props) == 0 { return } openingTrimmed := utils.TrimNodeTextRange(ctx.SourceFile, node) openingStart := openingTrimmed.Pos() leadChar := firstNonWhitespaceCharOnLine(openingStart) isUsingOperator := leadChar == '?' || leadChar == ':' elementIndent := reactutil.IndentLeading(text, lineMap, openingStart, indentChar) var propIndent int if indentIsFirst { propIndent = reactutil.NodeStartUTF16Column(ctx.SourceFile, props[0]) } else { propIndent = elementIndent + indentSize } nestedIndent := propIndent bumpApplied := false for _, prop := range props { if firstLineContainsBracket(prop) { isUsingOperator = false } if !reactutil.IsNodeFirstInLine(ctx.SourceFile, prop) { continue } if !bumpApplied && isUsingOperator && !indentIsFirst && !ignoreTernaryOperator { nestedIndent += indentSize bumpApplied = true isUsingOperator = false } actualIndent := reactutil.NodeStartIndent(ctx.SourceFile, prop, indentChar) if actualIndent != nestedIndent { reactutil.ReportIndentReplaceLeading(ctx, prop, nestedIndent, actualIndent, indentChar, indentType) } } } return rule.RuleListeners{ ast.KindJsxOpeningElement: check, ast.KindJsxSelfClosingElement: check, } }, }
JsxIndentPropsRule enforces JSX prop indentation.
Ported from eslint-plugin-react's `jsx-indent-props` rule. The rule walks every JsxOpeningElement / JsxSelfClosingElement, computes the expected prop indent (either `<element-indent> + indentSize` for the numeric / tab modes, or the column of the first prop for `'first'`), and reports each attribute whose leading-whitespace count differs.
tsgo↔ESTree shape adjustments (vs the upstream JS rule):
- Self-closing `<Foo />` is `JsxSelfClosingElement` with no wrapping `JsxElement`, so both `JsxOpeningElement` and `JsxSelfClosingElement` share the same listener.
- Source-line scans (line-start, leading whitespace, first non-WS char) run against `SourceFile.Text()`; line numbers come from the ECMA line map via `scanner.ComputeLineOfPosition`.
Ternary operator handling: upstream maintains a `line.isUsingOperator` flag that is set when the line containing the JSX `<` starts with `?` or `:` after whitespace. When that flag is on (and `'first'` mode is off and `ignoreTernaryOperator` is off), the FIRST prop that sits first-in-line receives an extra `indentSize` bump, after which the flag is cleared. We replicate that behaviour with a per-element `bumpApplied` boolean and a per-prop bracket reset (mirrors upstream's `useBracket` reset inside `getNodeIndent` — any prop whose first source line contains `<` cancels the pending bump, exactly the same way upstream's per-call side effect would).
Functions ¶
This section is empty.
Types ¶
This section is empty.