Skip to content

Commit

Permalink
feat(parser/renderer): attach list item to ancestor (#291)
Browse files Browse the repository at this point in the history
support attaching to any level of ancestor, for ordered,
unordered and labeled lists.

fixes #264

Signed-off-by: Xavier Coulon <[email protected]>
  • Loading branch information
xcoulon authored Feb 12, 2019
1 parent 061eb82 commit 6d9eb0e
Show file tree
Hide file tree
Showing 15 changed files with 17,267 additions and 15,574 deletions.
16 changes: 8 additions & 8 deletions pkg/parser/asciidoc-grammar.peg
Original file line number Diff line number Diff line change
Expand Up @@ -483,14 +483,14 @@ ListParagraphLine <-
return line, nil
}

ListItemContinuation <- "+" WS* EOL {
return types.NewListItemContinuation()
}
ListItemContinuation <- "+" WS* EOL

ContinuedDocumentElement<- ListItemContinuation element:DocumentElement{
return element, nil
ContinuedListElement <- blanklines:(BlankLine)* ListItemContinuation element:DocumentElement{
return types.NewContinuedListElement(-len(blanklines.([]interface{})), element) // offset is negative
}



// ------------------------------------------
// Ordered List Items
// ------------------------------------------
Expand Down Expand Up @@ -525,7 +525,7 @@ OrderedListItemPrefix <- WS* prefix:(
return prefix, nil
}

OrderedListItemContent <- elements:(ListParagraph+ ContinuedDocumentElement*) { // Another list or a literal paragraph immediately following a list item will be implicitly included in the list item
OrderedListItemContent <- elements:(ListParagraph+ ContinuedListElement*) { // Another list or a literal paragraph immediately following a list item will be implicitly included in the list item
return types.NewListItemContent(elements.([]interface{}))
}

Expand Down Expand Up @@ -567,7 +567,7 @@ UnorderedListItemCheckStyle <- &"[" style:(
return style, nil
}

UnorderedListItemContent <- elements:(ListParagraph+ ContinuedDocumentElement*) { // Another list or a literal paragraph immediately following a list item will be implicitly included in the list item
UnorderedListItemContent <- elements:(ListParagraph+ ContinuedListElement*) { // Another list or a literal paragraph immediately following a list item will be implicitly included in the list item
return types.NewListItemContent(elements.([]interface{}))
}

Expand All @@ -591,7 +591,7 @@ LabeledListItemSeparator <- ("::::" / ":::" / "::") {


LabeledListItemDescription <-
(WS / NEWLINE)+ elements:(ListParagraph / ContinuedDocumentElement)* { // TODO: replace with (ListParagraph+ ContinuedDocumentElement*) and use a single rule for all item contents ?
(WS / NEWLINE)+ elements:(ListParagraph / ContinuedListElement)* { // TODO: replace with (ListParagraph+ ContinuedListElement*) and use a single rule for all item contents ?
return types.NewListItemContent(elements.([]interface{}))
} / WS* EOL { // here, WS is optional since there is no description afterwards
return []interface{}{}, nil
Expand Down
21,485 changes: 10,764 additions & 10,721 deletions pkg/parser/asciidoc_parser.go

Large diffs are not rendered by default.

319 changes: 319 additions & 0 deletions pkg/parser/check_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
package parser_test

import (
"github.com/bytesparadise/libasciidoc/pkg/parser"
"github.com/bytesparadise/libasciidoc/pkg/types"
. "github.com/onsi/ginkgo"
)

var _ = Describe("checked lists", func() {

It("checklist with title and dashes", func() {
actualContent := `.Checklist
- [*] checked
- [x] also checked
- [ ] not checked
- normal list item`
expectedResult := types.UnorderedList{
Attributes: types.ElementAttributes{
types.AttrTitle: "Checklist",
},
Items: []types.UnorderedListItem{
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.Dash,
CheckStyle: types.Checked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Checked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "checked",
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.Dash,
CheckStyle: types.Checked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Checked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "also checked",
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.Dash,
CheckStyle: types.Unchecked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Unchecked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "not checked",
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.Dash,
CheckStyle: types.NoCheck,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "normal list item",
},
},
},
},
},
},
},
}
verify(GinkgoT(), expectedResult, actualContent, parser.Entrypoint("DocumentBlock"))
})

It("parent checklist with title and nested checklist", func() {
actualContent := `.Checklist
* [ ] parent not checked
** [*] checked
** [x] also checked
** [ ] not checked
* normal list item`
expectedResult := types.UnorderedList{
Attributes: types.ElementAttributes{
types.AttrTitle: "Checklist",
},
Items: []types.UnorderedListItem{
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.OneAsterisk,
CheckStyle: types.Unchecked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Unchecked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "parent not checked",
},
},
},
},
types.UnorderedList{
Attributes: types.ElementAttributes{},
Items: []types.UnorderedListItem{
{
Attributes: types.ElementAttributes{},
Level: 2,
BulletStyle: types.TwoAsterisks,
CheckStyle: types.Checked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Checked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "checked",
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 2,
BulletStyle: types.TwoAsterisks,
CheckStyle: types.Checked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Checked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "also checked",
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 2,
BulletStyle: types.TwoAsterisks,
CheckStyle: types.Unchecked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Unchecked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "not checked",
},
},
},
},
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.OneAsterisk,
CheckStyle: types.NoCheck,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "normal list item",
},
},
},
},
},
},
},
}
verify(GinkgoT(), expectedResult, actualContent, parser.Entrypoint("DocumentBlock"))
})

It("parent checklist with title and nested normal list", func() {
actualContent := `.Checklist
* [ ] parent not checked
** a normal list item
** another normal list item
* normal list item`
expectedResult := types.UnorderedList{
Attributes: types.ElementAttributes{
types.AttrTitle: "Checklist",
},
Items: []types.UnorderedListItem{
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.OneAsterisk,
CheckStyle: types.Unchecked,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{
types.AttrCheckStyle: types.Unchecked,
},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "parent not checked",
},
},
},
},
types.UnorderedList{
Attributes: types.ElementAttributes{},
Items: []types.UnorderedListItem{
{
Attributes: types.ElementAttributes{},
Level: 2,
BulletStyle: types.TwoAsterisks,
CheckStyle: types.NoCheck,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "a normal list item",
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 2,
BulletStyle: types.TwoAsterisks,
CheckStyle: types.NoCheck,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "another normal list item",
},
},
},
},
},
},
},
},
},
},
{
Attributes: types.ElementAttributes{},
Level: 1,
BulletStyle: types.OneAsterisk,
CheckStyle: types.NoCheck,
Elements: []interface{}{
types.Paragraph{
Attributes: types.ElementAttributes{},
Lines: []types.InlineElements{
{
types.StringElement{
Content: "normal list item",
},
},
},
},
},
},
},
}
verify(GinkgoT(), expectedResult, actualContent, parser.Entrypoint("DocumentBlock"))
})
})
Loading

0 comments on commit 6d9eb0e

Please sign in to comment.