@@ -11,6 +11,13 @@ import (
1111 yaml "go.yaml.in/yaml/v4"
1212)
1313
14+ var (
15+ commentLineRe = regexp .MustCompile (`^\s*#` )
16+ yamlDirectiveLineRe = regexp .MustCompile (`^\s*%YAML` )
17+ separatorLineRe = regexp .MustCompile (`^\s*---\s*$` )
18+ separatorPrefixRe = regexp .MustCompile (`^\s*---\s+` )
19+ )
20+
1421type yamlDecoder struct {
1522 decoder yaml.Decoder
1623
@@ -33,51 +40,72 @@ func NewYamlDecoder(prefs YamlPreferences) Decoder {
3340}
3441
3542func (dec * yamlDecoder ) processReadStream (reader * bufio.Reader ) (io.Reader , string , error ) {
36- var commentLineRegEx = regexp .MustCompile (`^\s*#` )
37- var yamlDirectiveLineRegEx = regexp .MustCompile (`^\s*%YA` )
3843 var sb strings.Builder
44+
3945 for {
40- peekBytes , err := reader .Peek ( 4 )
41- if errors .Is (err , io .EOF ) {
42- // EOF are handled else where..
46+ line , err := reader .ReadString ( '\n' )
47+ if errors .Is (err , io .EOF ) && line == "" {
48+ // no more data
4349 return reader , sb .String (), nil
44- } else if err != nil {
50+ }
51+ if err != nil && ! errors .Is (err , io .EOF ) {
4552 return reader , sb .String (), err
46- } else if string (peekBytes [0 ]) == "\n " {
47- _ , err := reader .ReadString ('\n' )
48- sb .WriteString ("\n " )
53+ }
54+
55+ // Determine newline style and strip it for inspection
56+ newline := ""
57+ if strings .HasSuffix (line , "\r \n " ) {
58+ newline = "\r \n "
59+ line = strings .TrimSuffix (line , "\r \n " )
60+ } else if strings .HasSuffix (line , "\n " ) {
61+ newline = "\n "
62+ line = strings .TrimSuffix (line , "\n " )
63+ }
64+
65+ trimmed := strings .TrimSpace (line )
66+
67+ // Document separator: exact line '---' or a '--- ' prefix followed by content
68+ if separatorLineRe .MatchString (trimmed ) {
69+ sb .WriteString ("$yqDocSeparator$" )
70+ sb .WriteString (newline )
4971 if errors .Is (err , io .EOF ) {
5072 return reader , sb .String (), nil
51- } else if err != nil {
52- return reader , sb .String (), err
5373 }
54- } else if string (peekBytes ) == "--- " {
55- _ , err := reader .ReadString (' ' )
56- sb .WriteString ("$yqDocSeparator$\n " )
57- if errors .Is (err , io .EOF ) {
58- return reader , sb .String (), nil
59- } else if err != nil {
60- return reader , sb .String (), err
74+ continue
75+ }
76+
77+ // Handle lines that start with '--- ' followed by more content (e.g. '--- cat')
78+ if separatorPrefixRe .MatchString (line ) {
79+ match := separatorPrefixRe .FindString (line )
80+ remainder := line [len (match ):]
81+ // normalize separator newline: if original had none, default to LF
82+ sepNewline := newline
83+ if sepNewline == "" {
84+ sepNewline = "\n "
6185 }
62- } else if string (peekBytes ) == "---\n " {
63- _ , err := reader .ReadString ('\n' )
64- sb .WriteString ("$yqDocSeparator$\n " )
65- if errors .Is (err , io .EOF ) {
86+ sb .WriteString ("$yqDocSeparator$" )
87+ sb .WriteString (sepNewline )
88+ // push the remainder back onto the reader and continue processing
89+ reader = bufio .NewReader (io .MultiReader (strings .NewReader (remainder ), reader ))
90+ if errors .Is (err , io .EOF ) && remainder == "" {
6691 return reader , sb .String (), nil
67- } else if err != nil {
68- return reader , sb .String (), err
6992 }
70- } else if commentLineRegEx .MatchString (string (peekBytes )) || yamlDirectiveLineRegEx .MatchString (string (peekBytes )) {
71- line , err := reader .ReadString ('\n' )
93+ continue
94+ }
95+
96+ // Comments, YAML directives, and blank lines are leading content
97+ if commentLineRe .MatchString (line ) || yamlDirectiveLineRe .MatchString (line ) || trimmed == "" {
7298 sb .WriteString (line )
99+ sb .WriteString (newline )
73100 if errors .Is (err , io .EOF ) {
74101 return reader , sb .String (), nil
75- } else if err != nil {
76- return reader , sb .String (), err
77102 }
78- } else {
79- return reader , sb .String (), nil
103+ continue
80104 }
105+
106+ // First non-leading line: push it back onto a reader and return
107+ originalLine := line + newline
108+ return io .MultiReader (strings .NewReader (originalLine ), reader ), sb .String (), nil
81109 }
82110}
83111
0 commit comments