diff --git a/caddyconfig/caddyfile/formatter.go b/caddyconfig/caddyfile/formatter.go index 14315a3f1..d25aad2d3 100644 --- a/caddyconfig/caddyfile/formatter.go +++ b/caddyconfig/caddyfile/formatter.go @@ -106,6 +106,34 @@ func Format(input []byte) []byte { beginningOfLine = true } + flushOpenBrace := func() { + if nesting == 0 && last == '}' { + nextLine() + nextLine() + } + + openBrace = false + if openBraceOwnLine && previousLineWasTopLevelImport { + if last != '\n' { + nextLine() + } + indent() + } else if beginningOfLine { + indent() + } else if !openBraceSpace || !unicode.IsSpace(last) { + write(' ') + } + write('{') + openBraceWritten = true + openBraceOwnLine = false + nextLine() + newLines = 0 + // prevent infinite nesting from ridiculous inputs (issue #4169) + if nesting < 10 { + nesting++ + } + } + for { ch, _, err := rdr.ReadRune() if err != nil { @@ -270,36 +298,15 @@ func Format(input []byte) []byte { } if openBrace && spacePrior && !openBraceWritten { - if nesting == 0 && last == '}' { - nextLine() - nextLine() - } - - openBrace = false - if openBraceOwnLine && previousLineWasTopLevelImport { - if last != '\n' { - nextLine() - } - indent() - } else if beginningOfLine { - indent() - } else if !openBraceSpace || !unicode.IsSpace(last) { - write(' ') - } - write('{') - openBraceWritten = true - openBraceOwnLine = false - nextLine() - newLines = 0 - // prevent infinite nesting from ridiculous inputs (issue #4169) - if nesting < 10 { - nesting++ - } + flushOpenBrace() } switch { case ch == '{': finishToken() + if openBrace && !openBraceWritten { + flushOpenBrace() + } openBrace = true openBraceSpace = spacePrior && !beginningOfLine openBraceOwnLine = newLines > 0 @@ -367,6 +374,10 @@ func Format(input []byte) []byte { beginningOfLine = false } + if openBrace && !openBraceWritten { + flushOpenBrace() + } + // the Caddyfile does not need any leading or trailing spaces, but... trimmedResult := bytes.TrimSpace(out.Bytes()) diff --git a/caddyconfig/caddyfile/formatter_test.go b/caddyconfig/caddyfile/formatter_test.go index e3be227fb..7eef04766 100644 --- a/caddyconfig/caddyfile/formatter_test.go +++ b/caddyconfig/caddyfile/formatter_test.go @@ -495,6 +495,28 @@ import ./conf.d/matcher_not_my_subnet.caddy order appsec after crowdsec }`, }, + { + description: "keep an opening brace that ends the input", + input: `localhost {`, + expect: `localhost {`, + }, + { + description: "keep a standalone opening brace that ends the input", + input: `{`, + expect: `{`, + }, + { + description: "keep adjacent opening braces that end the input", + input: `{{`, + expect: `{ + {`, + }, + { + description: "keep spaced opening braces that end the input", + input: `{ {`, + expect: `{ + {`, + }, } { // the formatter should output a trailing newline, // even if the tests aren't written to expect that