Skip to content

Commit

Permalink
feat: preserve line breaks from original input (#412)
Browse files Browse the repository at this point in the history
* feat: preserve line breaks from original input
* docs: fix spelling error in comment

---------

Co-authored-by: Hilmar Falkenberg <hilmar.falkenberg@sap.com>
  • Loading branch information
mcwarman and hilmarf authored Nov 2, 2024
1 parent 9fabf36 commit 8713f53
Show file tree
Hide file tree
Showing 2 changed files with 339 additions and 14 deletions.
61 changes: 58 additions & 3 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,49 @@ func readNode(p []byte, node Node) (int, error) {
return size, nil
}

func checkLineBreak(t *token.Token) bool {
if t.Prev != nil {
lbc := "\n"
prev := t.Prev
var adjustment int
// if the previous type is sequence entry use the previous type for that
if prev.Type == token.SequenceEntryType {
// as well as switching to previous type count any new lines in origin to account for:
// -
// b: c
adjustment = strings.Count(strings.TrimRight(t.Origin, lbc), lbc)
if prev.Prev != nil {
prev = prev.Prev
}
}
lineDiff := t.Position.Line - prev.Position.Line - 1
if lineDiff > 0 {
if prev.Type == token.StringType {
// Remove any line breaks included in multiline string
adjustment += strings.Count(strings.TrimRight(strings.TrimSpace(prev.Origin), lbc), lbc)
}
// Due to the way that comment parsing works its assumed that when a null value does not have new line in origin
// it was squashed therefore difference is ignored.
//foo:
// bar:
// # comment
// baz: 1
//becomes
//foo:
// bar: null # comment
//
// baz: 1
if prev.Type == token.NullType {
return strings.Count(prev.Origin, lbc) > 0
}
if lineDiff-adjustment > 0 {
return true
}
}
}
return false
}

// Null create node for null value
func Null(tk *token.Token) *NullNode {
return &NullNode{
Expand Down Expand Up @@ -1390,6 +1433,9 @@ func (n *MappingValueNode) String() string {

func (n *MappingValueNode) toString() string {
space := strings.Repeat(" ", n.Key.GetToken().Position.Column-1)
if checkLineBreak(n.Key.GetToken()) {
space = fmt.Sprintf("%s%s", "\n", space)
}
keyIndentLevel := n.Key.GetToken().Position.IndentLevel
valueIndentLevel := n.Value.GetToken().Position.IndentLevel
keyComment := n.Key.GetComment()
Expand Down Expand Up @@ -1563,6 +1609,11 @@ func (n *SequenceNode) blockStyleString() string {

for idx, value := range n.Values {
valueStr := value.String()
newLinePrefix := ""
if strings.HasPrefix(valueStr, "\n") {
valueStr = valueStr[1:]
newLinePrefix = "\n"
}
splittedValues := strings.Split(valueStr, "\n")
trimmedFirstValue := strings.TrimLeft(splittedValues[0], " ")
diffLength := len(splittedValues[0]) - len(trimmedFirstValue)
Expand All @@ -1585,9 +1636,10 @@ func (n *SequenceNode) blockStyleString() string {
}
newValue := strings.Join(newValues, "\n")
if len(n.ValueHeadComments) == len(n.Values) && n.ValueHeadComments[idx] != nil {
values = append(values, n.ValueHeadComments[idx].StringWithSpace(n.Start.Position.Column-1))
values = append(values, fmt.Sprintf("%s%s", newLinePrefix, n.ValueHeadComments[idx].StringWithSpace(n.Start.Position.Column-1)))
newLinePrefix = ""
}
values = append(values, fmt.Sprintf("%s- %s", space, newValue))
values = append(values, fmt.Sprintf("%s%s- %s", newLinePrefix, space, newValue))
}
if n.FootComment != nil {
values = append(values, n.FootComment.StringWithSpace(n.Start.Position.Column-1))
Expand Down Expand Up @@ -1880,10 +1932,13 @@ func (n *CommentGroupNode) StringWithSpace(col int) string {
values := []string{}
space := strings.Repeat(" ", col)
for _, comment := range n.Comments {
space := space
if checkLineBreak(comment.Token) {
space = fmt.Sprintf("%s%s", "\n", space)
}
values = append(values, space+comment.String())
}
return strings.Join(values, "\n")

}

// MarshalYAML encodes to a YAML text
Expand Down
Loading

0 comments on commit 8713f53

Please sign in to comment.