Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(parser): improve support for cross-references #865

Merged
merged 1 commit into from
Nov 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions pkg/parser/cross_reference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,81 @@ some content`
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("to attached element in a list", func() {
source := `a reference to <<table>>

. list element
+
[#table]
.The table
|===
| A | B
|===
`

expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{
Content: "a reference to ",
},
&types.InternalCrossReference{
ID: "table",
},
},
},
&types.List{
Kind: types.OrderedListKind,
Elements: []types.ListElement{
&types.OrderedListElement{
Style: types.Arabic,
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{
Content: "list element",
},
},
},
&types.Table{
Attributes: types.Attributes{
types.AttrID: "table",
types.AttrTitle: "The table",
},
Rows: []*types.TableRow{
{
Cells: []*types.TableCell{
{
Elements: []interface{}{
&types.StringElement{
Content: "A ",
},
},
},
{
Elements: []interface{}{
&types.StringElement{
Content: "B",
},
},
},
},
},
},
},
},
},
},
},
},
ElementReferences: types.ElementReferences{
"table": "The table",
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})
})

Context("external references", func() {
Expand Down
4 changes: 1 addition & 3 deletions pkg/parser/document_processing_aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ func aggregate(ctx *ParseContext, fragmentStream <-chan types.DocumentFragment)
}
// also, check if the element has refs
if e, ok := element.(types.Referencable); ok {
if id, title := e.Ref(); id != "" && title != nil {
refs[id] = title
}
e.Reference(refs)
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/parser/q_a_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ What is the answer to the Ultimate Question?:: 42`
},
},
},
ElementReferences: types.ElementReferences{
"quiz": "Q&A",
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})
Expand Down
3 changes: 3 additions & 0 deletions pkg/parser/unordered_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ var _ = Describe("unordered lists", func() {
},
},
},
ElementReferences: types.ElementReferences{
"listID": "mytitle",
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})
Expand Down
110 changes: 101 additions & 9 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type BlockWithLocation interface {
}

type Referencable interface {
Ref() (string, interface{})
Reference(refs ElementReferences)
}

// ------------------------------------------
Expand Down Expand Up @@ -717,6 +717,20 @@ func (l *List) AddElement(element interface{}) error {
return errors.Errorf("cannot add element of type '%T' to list of kind '%s'", element, l.Kind)
}

func (l *List) Reference(refs ElementReferences) {
id := l.Attributes.GetAsStringWithDefault(AttrID, "")
title := l.Attributes[AttrTitle]
if id != "" && title != nil {
refs[id] = title
}
// also, visit elements
for _, e := range l.Elements {
if e, ok := e.(Referencable); ok {
e.Reference(refs)
}
}
}

func (l *List) LastElement() ListElement {
if len(l.Elements) == 0 {
return nil
Expand Down Expand Up @@ -898,6 +912,22 @@ func NewCalloutListElement(ref int, content RawLine) (*CalloutListElement, error
}, nil
}

var _ Referencable = &CalloutListElement{}

func (e *CalloutListElement) Reference(refs ElementReferences) {
id := e.Attributes.GetAsStringWithDefault(AttrID, "")
title := e.Attributes[AttrTitle]
if id != "" && title != nil {
refs[id] = title
}
// also, visit elements
for _, e := range e.Elements {
if e, ok := e.(Referencable); ok {
e.Reference(refs)
}
}
}

// checks if the given list element matches the level of this element
func (e *CalloutListElement) matchesStyle(other ListElement) bool {
_, ok := other.(*CalloutListElement)
Expand Down Expand Up @@ -991,6 +1021,22 @@ func NewOrderedListElement(prefix OrderedListElementPrefix, content interface{})
}, nil
}

var _ Referencable = &OrderedListElement{}

func (e *OrderedListElement) Reference(refs ElementReferences) {
id := e.Attributes.GetAsStringWithDefault(AttrID, "")
title := e.Attributes[AttrTitle]
if id != "" && title != nil {
refs[id] = title
}
// also, visit elements
for _, e := range e.Elements {
if e, ok := e.(Referencable); ok {
e.Reference(refs)
}
}
}

// checks if the given list element matches the level of this element
func (e *OrderedListElement) matchesStyle(other ListElement) bool {
if element, ok := other.(*OrderedListElement); ok {
Expand Down Expand Up @@ -1105,6 +1151,22 @@ func NewUnorderedListElement(prefix UnorderedListElementPrefix, checkstyle inter
}, nil
}

var _ Referencable = &UnorderedListElement{}

func (e *UnorderedListElement) Reference(refs ElementReferences) {
id := e.Attributes.GetAsStringWithDefault(AttrID, "")
title := e.Attributes[AttrTitle]
if id != "" && title != nil {
refs[id] = title
}
// also, visit elements
for _, e := range e.Elements {
if e, ok := e.(Referencable); ok {
e.Reference(refs)
}
}
}

// checks if the given list element matches the level of this element
func (e *UnorderedListElement) matchesStyle(other ListElement) bool {
if other, ok := other.(*UnorderedListElement); ok {
Expand Down Expand Up @@ -1331,6 +1393,22 @@ func NewLabeledListElement(level int, term, description interface{}) (*LabeledLi
}, nil
}

var _ Referencable = &LabeledListElement{}

func (e *LabeledListElement) Reference(refs ElementReferences) {
id := e.Attributes.GetAsStringWithDefault(AttrID, "")
title := e.Attributes[AttrTitle]
if id != "" && title != nil {
refs[id] = title
}
// also, visit elements
for _, e := range e.Elements {
if e, ok := e.(Referencable); ok {
e.Reference(refs)
}
}
}

// making sure that the `ListElement` interface is implemented by `LabeledListElement`
var _ ListElement = &LabeledListElement{}

Expand Down Expand Up @@ -1509,10 +1587,12 @@ func (p *Paragraph) mapAttributes() {

var _ Referencable = &Paragraph{}

func (p *Paragraph) Ref() (string, interface{}) {
func (p *Paragraph) Reference(refs ElementReferences) {
id := p.Attributes.GetAsStringWithDefault(AttrID, "")
title := p.Attributes[AttrTitle]
return id, title
if id != "" && title != nil {
refs[id] = title
}
}

var _ WithFootnotes = &Paragraph{}
Expand Down Expand Up @@ -1982,10 +2062,18 @@ func (b *DelimitedBlock) mapAttributes() {

var _ Referencable = &DelimitedBlock{}

func (b *DelimitedBlock) Ref() (string, interface{}) {
func (b *DelimitedBlock) Reference(refs ElementReferences) {
id := b.Attributes.GetAsStringWithDefault(AttrID, "")
title := b.Attributes[AttrTitle]
return id, title
if id != "" && title != nil {
refs[id] = title
}
// also, visit elements
for _, e := range b.Elements {
if e, ok := e.(Referencable); ok {
e.Reference(refs)
}
}
}

// TODO: not needed?
Expand Down Expand Up @@ -2098,9 +2186,11 @@ func (s *Section) resolveID(attrs Attributes) (string, error) {

var _ Referencable = &Section{}

func (s *Section) Ref() (string, interface{}) {
func (s *Section) Reference(refs ElementReferences) {
id := s.Attributes.GetAsStringWithDefault(AttrID, "")
return id, s.Title
if id != "" && s.Title != nil {
refs[id] = s.Title
}
}

var _ WithElementAddition = &Section{}
Expand Down Expand Up @@ -3049,10 +3139,12 @@ func (t *Table) SetAttributes(attributes Attributes) {

var _ Referencable = &Table{}

func (t *Table) Ref() (string, interface{}) {
func (t *Table) Reference(refs ElementReferences) {
id := t.Attributes.GetAsStringWithDefault(AttrID, "")
title := t.Attributes[AttrTitle]
return id, title
if id != "" && title != nil {
refs[id] = title
}
}

type HAlign string
Expand Down