diff --git a/pkg/parser/section_test.go b/pkg/parser/section_test.go index 0453b9ac..35b4ea4d 100644 --- a/pkg/parser/section_test.go +++ b/pkg/parser/section_test.go @@ -30,14 +30,14 @@ var _ = Describe("sections", func() { Expect(ParseDocument(source)).To(MatchDocument(expected)) }) - It("header with many spaces around content", func() { - source := "= a header " + It("header with trailing spaces", func() { + source := "= a header " expected := &types.Document{ Elements: []interface{}{ &types.DocumentHeader{ Title: []interface{}{ &types.StringElement{ - Content: "a header ", + Content: "a header", }, }, }, @@ -46,6 +46,42 @@ var _ = Describe("sections", func() { Expect(ParseDocument(source)).To(MatchDocument(expected)) }) + It("section with trailing spaces", func() { + source := "== a section " + expected := &types.Document{ + Elements: []interface{}{ + &types.Section{ + Level: 1, + Attributes: types.Attributes{ + types.AttrID: "_a_section", + }, + Title: []interface{}{ + &types.StringElement{ + Content: "a section", + }, + }, + }, + }, + ElementReferences: types.ElementReferences{ + "_a_section": []interface{}{ + &types.StringElement{ + Content: "a section", + }, + }, + }, + TableOfContents: &types.TableOfContents{ + MaxDepth: 2, + Sections: []*types.ToCSection{ + { + ID: "_a_section", + Level: 1, + }, + }, + }, + } + Expect(ParseDocument(source)).To(MatchDocument(expected)) + }) + It("header and paragraph", func() { source := `= a header diff --git a/pkg/renderer/sgml/html5/cross_reference_test.go b/pkg/renderer/sgml/html5/cross_reference_test.go index 858bd60a..fa1136b8 100644 --- a/pkg/renderer/sgml/html5/cross_reference_test.go +++ b/pkg/renderer/sgml/html5/cross_reference_test.go @@ -139,10 +139,10 @@ with some content linked to <>!` Expect(RenderHTML(source)).To(MatchHTML(expected)) }) - It("natural ref to section with plaintext title", func() { + It("natural ref to section with plaintext title with trailing spaces", func() { source := `see <
>. -== Section 1` +== Section 1 ` // trailing spaces in the title expected := `

see Section 1.

diff --git a/pkg/types/types.go b/pkg/types/types.go index 933072d3..2eb621d4 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -298,7 +298,7 @@ func NewDocumentHeader(info interface{}, extraAttrs []interface{}) (*DocumentHea header := &DocumentHeader{} elements := make([]interface{}, 0, 2+len(extraAttrs)) // estimated max capacity if info, ok := info.(*DocumentInformation); ok { - header.Title = info.Title + header.Title = TrimTrailingSpaces(info.Title) if len(info.Authors) > 0 { // header.Authors = info.Authors elements = append(elements, &AttributeDeclaration{ @@ -2492,7 +2492,7 @@ func (s *Section) SetTitle(title []interface{}) { }) title = title[:len(title)-1] } - s.Title = title + s.Title = TrimTrailingSpaces(title) } // GetAttributes returns this section's attributes diff --git a/pkg/types/types_utils.go b/pkg/types/types_utils.go index a51e771c..04b63c01 100644 --- a/pkg/types/types_utils.go +++ b/pkg/types/types_utils.go @@ -162,15 +162,12 @@ func stringify(element interface{}) string { } } -// TrimLeft returns a slice of elements where the -// `strings.TrimLeft` func was applied on the content of the first entry -// if it is a `*StringElement` -func TrimLeft(elements []interface{}, cutset string) []interface{} { - if len(elements) == 0 { - return elements - } - if first, ok := elements[0].(*StringElement); ok { - first.Content = strings.TrimLeft(first.Content, cutset) +// TrimTrailingSpaces trims trailing spaces on the last element (if applicable) +func TrimTrailingSpaces(elements []interface{}) []interface{} { + if len(elements) > 0 { + if s, ok := elements[len(elements)-1].(*StringElement); ok { + s.Content = strings.TrimRight(s.Content, " ") + } } return elements } diff --git a/pkg/types/types_utils_test.go b/pkg/types/types_utils_test.go index f5610d36..715145cf 100644 --- a/pkg/types/types_utils_test.go +++ b/pkg/types/types_utils_test.go @@ -31,57 +31,80 @@ var _ = Describe("convert to inline elements", func() { }) }) -// var _ = DescribeTable("TrimLeft", +var _ = DescribeTable("TrimTrailingSpaces", -// func(source, expected []interface{}) { + func(source, expected []interface{}) { + Expect(types.TrimTrailingSpaces(source)).To(Equal(expected)) + }, + Entry("empty slice", + []interface{}{}, + []interface{}{}), + + Entry("single element with trailing spaces", + []interface{}{ + &types.StringElement{ + Content: "pasta ", // trailing spaces + }, + }, + []interface{}{ + &types.StringElement{ + Content: "pasta", // timmed + }, + }), -// }, -// Entry("empty slice", -// []interface{}{}, -// []interface{}{}), + Entry("multiple elements with trailing spaces", + []interface{}{ + &types.StringElement{ + Content: "cookies", + }, + &types.InlineLink{}, + &types.StringElement{ + Content: "pasta ", // trailing spaces + }, + }, + []interface{}{ + &types.StringElement{ + Content: "cookies", + }, + &types.InlineLink{}, + &types.StringElement{ + Content: "pasta", // timmed + }, + }), -// Entry("valid slice", -// []interface{}{ -// &types.StringElement{ -// Content: " cookies", -// }, -// &types.StringElement{ -// Content: " pasta", -// }, -// }, -// []interface{}{ -// &types.StringElement{ -// Content: "cookies", // trimmed -// }, -// &types.StringElement{ -// Content: " pasta", -// }, -// }), + Entry("multiple elements without trailing spaces", + []interface{}{ + &types.StringElement{ + Content: "cookies", + }, + &types.InlineLink{}, + &types.StringElement{ + Content: "pasta", // no trailing spaces + }, + }, + []interface{}{&types.StringElement{ + Content: "cookies", + }, + &types.InlineLink{}, + &types.StringElement{ + Content: "pasta", // no change + }, + }), -// Entry("noop slice", -// []interface{}{ -// &types.SpecialCharacter{ -// Name: ">", -// }, -// &types.StringElement{ -// Content: " cookies", -// }, -// &types.StringElement{ -// Content: " pasta", -// }, -// }, -// []interface{}{ -// &types.SpecialCharacter{ -// Name: ">", -// }, -// &types.StringElement{ -// Content: " cookies", // not trimmed -// }, -// &types.StringElement{ -// Content: " pasta", -// }, -// }), -// ) + Entry("noop", + []interface{}{ + &types.StringElement{ + Content: "cookies", + }, + &types.InlineLink{}, // not a StringElement + }, + []interface{}{ + &types.StringElement{ + Content: "cookies", + }, + &types.InlineLink{}, + }), +) var _ = DescribeTable("split elements per line", func(elements []interface{}, expected [][]interface{}) {