Repository: google/yamlfmt (go)

Issue:
Support multiple documents in single file
The default `Unmarshal` behaviour in `yaml.v3` will only read and output the first document in a multi-document yaml file. I was unaware that this was possible, let alone common in Kubernetes so I did not test it initially. 

The way to make `yaml.v3` parse these properly is to to make a `Decoder` for the whole document, and decode them one at a time in a loop. This behaviour might diverge heavily from the basic formatter, so it might need to be an entirely new one, but I will see if I can make it work by default.

Pull request:
basic: Support formatting multi-document files
Closes #14 

Files with multiple documents are more common than I originally thought,
so it is best that I switch to Decode and Encode for this formatter that
will properly format all documents in multi-document files.

Patch:
diff --git a/formatters/basic/formatter.go b/formatters/basic/formatter.go
index 194db49..8323559 100644
--- a/formatters/basic/formatter.go
+++ b/formatters/basic/formatter.go
@@ -16,6 +16,8 @@ package basic
 
 import (
 	"bytes"
+	"errors"
+	"io"
 
 	"gopkg.in/yaml.v3"
 )
@@ -31,17 +33,29 @@ func (f *BasicFormatter) Type() string {
 }
 
 func (f *BasicFormatter) Format(yamlContent []byte) ([]byte, error) {
-	var unmarshalled yaml.Node
-	err := yaml.Unmarshal(yamlContent, &unmarshalled)
-	if err != nil {
-		return nil, err
+	decoder := yaml.NewDecoder(bytes.NewReader(yamlContent))
+	documents := []yaml.Node{}
+	for {
+		var docNode yaml.Node
+		err := decoder.Decode(&docNode)
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				break
+			}
+			return nil, err
+		}
+		documents = append(documents, docNode)
 	}
+
 	var b bytes.Buffer
 	e := yaml.NewEncoder(&b)
 	e.SetIndent(f.Config.Indent)
-	err = e.Encode(&unmarshalled)
-	if err != nil {
-		return nil, err
+	for _, doc := range documents {
+		err := e.Encode(&doc)
+		if err != nil {
+			return nil, err
+		}
 	}
+
 	return b.Bytes(), nil
 }


Test patch:
diff --git a/formatters/basic/formatter_test.go b/formatters/basic/formatter_test.go
index a3dd934..281d43e 100644
--- a/formatters/basic/formatter_test.go
+++ b/formatters/basic/formatter_test.go
@@ -53,3 +53,19 @@ a:`
 		t.Fatalf("keys were reordered:\n%s", s)
 	}
 }
+
+func TestFormatterParsesMultipleDocuments(t *testing.T) {
+	f := &basic.BasicFormatter{Config: basic.DefaultConfig()}
+
+	yaml := `b:
+---
+a:
+`
+	s, err := f.Format([]byte(yaml))
+	if err != nil {
+		t.Fatalf("expected formatting to pass, returned error: %v", err)
+	}
+	if len(s) != len([]byte(yaml)) {
+		t.Fatalf("expected yaml not to change, result: %s", string(s))
+	}
+}