Skip to content

Commit

Permalink
feat(parser/renderer): support Open Blocks without masquerading
Browse files Browse the repository at this point in the history
Fixes #1014

Signed-off-by: Xavier Coulon <xcoulon@redhat.com>
  • Loading branch information
xcoulon committed May 16, 2022
1 parent efa738e commit 899f796
Show file tree
Hide file tree
Showing 24 changed files with 18,802 additions and 17,407 deletions.
122 changes: 122 additions & 0 deletions pkg/parser/delimited_block_open_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package parser_test

import (
"github.com/bytesparadise/libasciidoc/pkg/types"
. "github.com/bytesparadise/libasciidoc/testsupport"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("open blocks", func() {

Context("in final documents", func() {

Context("without masquerade", func() {

It("with single paragraph", func() {
source := `--
some content
--`
expected := &types.Document{
Elements: []interface{}{
&types.DelimitedBlock{
Kind: types.Open,
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{
Content: `some content`,
},
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with table", func() {
source := `[#block-id]
.Block Title
--
[cols="2*^"]
|===
a|
[#id]
.A title
image::image.png[]
a|
[#another-id]
.Another title
image::another-image.png[]
|===
--`
expected := &types.Document{
Elements: []interface{}{
&types.DelimitedBlock{
Kind: types.Open,
Attributes: types.Attributes{
types.AttrID: "block-id",
types.AttrTitle: "Block Title",
},
Elements: []interface{}{
&types.Table{
Attributes: types.Attributes{
types.AttrCols: []interface{}{
&types.TableColumn{
Multiplier: 2,
HAlign: types.HAlignCenter,
VAlign: types.VAlignTop,
Weight: 1,
},
},
},
Rows: []*types.TableRow{
{
Cells: []*types.TableCell{
{
Format: "a",
Elements: []interface{}{
&types.ImageBlock{
Attributes: types.Attributes{
types.AttrID: "id",
types.AttrTitle: "A title",
},
Location: &types.Location{
Path: "image.png",
},
},
},
},
{
Format: "a",
Elements: []interface{}{
&types.ImageBlock{
Attributes: types.Attributes{
types.AttrID: "another-id",
types.AttrTitle: "Another title",
},
Location: &types.Location{
Path: "another-image.png",
},
},
},
},
},
},
},
},
},
},
},
ElementReferences: types.ElementReferences{
"block-id": "Block Title",
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})
})
})
})
4 changes: 2 additions & 2 deletions pkg/parser/document_processing_apply_substitutions.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func applySubstitutionsOnWithElements(ctx *ParseContext, b types.WithElements, o
return nil
case *types.DelimitedBlock:
switch b.Kind {
case types.Example, types.Quote, types.Sidebar:
case types.Example, types.Quote, types.Sidebar, types.Open: // TODO: add a func on *types.DelimitedBlock to avoid checking the exact same kinds in multiple places
for _, e := range b.GetElements() {
if err := applySubstitutionsOnElement(ctx, e, opts...); err != nil {
return err
Expand Down Expand Up @@ -779,7 +779,7 @@ func defaultSubstitutions(b types.WithElements) ([]string, error) {
switch b.Kind {
case types.Listing, types.Fenced, types.Literal:
return verbatimSubstitutions(), nil
case types.Example, types.Quote, types.Verse, types.Sidebar, types.MarkdownQuote:
case types.Example, types.Quote, types.Verse, types.Sidebar, types.MarkdownQuote, types.Open:
return normalSubstitutions(), nil
case types.Comment, types.Passthrough:
return noneSubstitutions(), nil
Expand Down
51 changes: 20 additions & 31 deletions pkg/parser/document_processing_parse_fragments.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,8 @@ func reparseElement(ctx *ParseContext, element interface{}) error {
return err
}
case *types.DelimitedBlock:
switch e.Kind {
case types.Example, types.Quote, types.Sidebar:
if err := reparseDelimitedBlock(ctx, e); err != nil {
return err
}
if err := reparseDelimitedBlock(ctx, e); err != nil {
return err
}
}
return nil
Expand Down Expand Up @@ -160,36 +157,24 @@ func reparseTableCell(ctx *ParseContext, c *types.TableCell) error {
}

func reparseDelimitedBlock(ctx *ParseContext, b *types.DelimitedBlock) error {
if err := reparseDelimitedBlockElements(ctx, b); err != nil {
return err
}
log.Debugf("reparsing content of delimited block of kind '%s'", b.Kind)
for _, e := range b.Elements { // TODO: change the grammar rules of these delimited blocks to avoid 2nd parsing
switch e := e.(type) {
case *types.DelimitedBlock:
switch e.Kind {
case types.Example, types.Quote, types.Sidebar:
if err := reparseDelimitedBlock(ctx, e); err != nil {
return err
}
switch b.Kind {
case types.Example, types.Quote, types.Sidebar, types.Open:
log.Debugf("parsing elements of delimited block of kind '%s'", b.Kind)
opts := append(ctx.Opts, Entrypoint("DelimitedBlockElements"), withinDelimitedBlock(true))
elements, err := reparseElements(b.Elements, opts...)
if err != nil {
return err
}
b.Elements = elements
for _, e := range b.Elements { // TODO: change the grammar rules of these delimited blocks to avoid 2nd parsing
if err := reparseElement(ctx, e); err != nil {
return err
}
}
}
return nil
}

// TODO: merge into `reparseDelimitedBlock` above?
func reparseDelimitedBlockElements(ctx *ParseContext, b *types.DelimitedBlock) error {
log.Debugf("parsing elements of delimited block of kind '%s'", b.Kind)
opts := append(ctx.Opts, Entrypoint("DelimitedBlockElements"), withinDelimitedBlock(true))
elements, err := reparseElements(b.Elements, opts...)
if err != nil {
return err
}
b.Elements = elements
return nil
}

func reparseElements(elements []interface{}, opts ...Option) ([]interface{}, error) {
content, placeholders := serialize(elements)
elmts, err := Parse("", content, opts...)
Expand All @@ -199,8 +184,12 @@ func reparseElements(elements []interface{}, opts ...Option) ([]interface{}, err
switch elmts := elmts.(type) {
case []interface{}:
// case where last element is `nil` because the parser found a standlone attribute
if len(elmts) > 0 && elmts[len(elmts)-1] == nil {
elmts = elmts[:len(elmts)-1]
for {
if len(elmts) > 0 && elmts[len(elmts)-1] == nil {
elmts = elmts[:len(elmts)-1]
} else {
break
}
}
return placeholders.restore(elmts), nil
default:
Expand Down
Loading

0 comments on commit 899f796

Please sign in to comment.