Skip to content

Commit

Permalink
feature(parser/renderer): unordered lists should support style (#660)
Browse files Browse the repository at this point in the history
This converts unordered lists so that they can support multiple
roles, and the style attribute properly.  It includes both the
parser side and renderer side changes.  The templates were
converted to use the exact HTML output that asciidoctor emits.

Fixes #658
  • Loading branch information
gdamore authored Jun 28, 2020
1 parent 6b342f4 commit c93bc82
Show file tree
Hide file tree
Showing 8 changed files with 2,383 additions and 2,251 deletions.
4,496 changes: 2,248 additions & 2,248 deletions pkg/parser/parser.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/parser/parser.peg
Original file line number Diff line number Diff line change
Expand Up @@ -764,8 +764,8 @@ OrderedListItemContent <- elements:(ListParagraph+) {
// ------------------------------------------
// Unordered List Items
// ------------------------------------------
UnorderedListItem <- attributes:(Attributes)? prefix:(UnorderedListItemPrefix) checkstyle:(UnorderedListItemCheckStyle)? content:(UnorderedListItemContent) {
return types.NewUnorderedListItem(prefix.(types.UnorderedListItemPrefix), checkstyle, content.([]interface{}), attributes)
UnorderedListItem <- attrs:(BlockAttrs)* prefix:(UnorderedListItemPrefix) checkstyle:(UnorderedListItemCheckStyle)? content:(UnorderedListItemContent) {
return types.NewUnorderedListItem(prefix.(types.UnorderedListItemPrefix), checkstyle, content.([]interface{}), attrs)
}

UnorderedListItemPrefix <-
Expand Down
33 changes: 33 additions & 0 deletions pkg/parser/unordered_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,39 @@ var _ = Describe("unordered lists", func() {
}
Expect(ParseDraftDocument(source)).To(MatchDraftDocument(expected))
})
It("unordered list with style ID, title, role and a single item", func() {
source := `.mytitle
[square#listID]
[.myrole]
* a list item`
expected := types.DraftDocument{
Blocks: []interface{}{
types.UnorderedListItem{
Attributes: types.Attributes{
types.AttrTitle: "mytitle",
types.AttrID: "listID",
types.AttrCustomID: true,
types.AttrRole: "myrole",
types.AttrStyle: "square",
},
Level: 1,
BulletStyle: types.OneAsterisk,
CheckStyle: types.NoCheck,
Elements: []interface{}{
types.Paragraph{
Lines: [][]interface{}{
{
types.StringElement{Content: "a list item"},
},
},
},
},
},
},
}
Expect(ParseDraftDocument(source)).To(MatchDraftDocument(expected))
})

It("unordered list with a title and a single item", func() {
source := `.a title
* a list item`
Expand Down
14 changes: 14 additions & 0 deletions pkg/renderer/sgml/element_style.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package sgml

import (
"text/template"

"github.com/bytesparadise/libasciidoc/pkg/types"
)

func (r *sgmlRenderer) renderElementStyle(attrs types.Attributes) sanitized {
if id, ok := attrs[types.AttrStyle].(string); ok {
return sanitized(template.HTMLEscapeString(id))
}
return ""
}
3 changes: 2 additions & 1 deletion pkg/renderer/sgml/html5/unordered_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package html5
const (
unorderedListTmpl = `<div{{ if .ID }} id="{{ .ID }}"{{ end }}` +
` class="ulist{{ if .Checklist }} checklist{{ end }}` +
`{{ if .Style }} {{ .Style }}{{ end }}` +
`{{ if .Roles }} {{ .Roles }}{{ end }}"` +
">\n" +
"{{ if .Title }}<div class=\"title\">{{ .Title }}</div>\n{{ end }}" +
"<ul{{ if .Checklist }} class=\"checklist\"{{ end }}>\n" +
"<ul{{ if .Checklist }} class=\"checklist\"{{ else if .Style }} class=\"{{ .Style }}\"{{ end }}>\n" +
"{{ .Content }}</ul>\n</div>"

unorderedListItemTmpl = "<li>\n{{ .Content }}\n</li>\n"
Expand Down
41 changes: 41 additions & 0 deletions pkg/renderer/sgml/html5/unordered_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,26 @@ and a standalone paragraph`
Expect(RenderHTML(source)).To(MatchHTML(expected))
})

It("simple unordered list with style id, title and role", func() {
source := `.mytitle
[#foo]
[disc.myrole]
* item 1
* item 2`
expected := `<div id="foo" class="ulist disc myrole">
<div class="title">mytitle</div>
<ul class="disc">
<li>
<p>item 1</p>
</li>
<li>
<p>item 2</p>
</li>
</ul>
</div>`
Expect(RenderHTML(source)).To(MatchHTML(expected))
})

It("simple unordered list with continuation", func() {
source := `* item 1
+
Expand Down Expand Up @@ -273,6 +293,27 @@ var _ = Describe("checklists", func() {
Expect(RenderHTML(source)).To(MatchHTML(expected))
})

It("simple checklist with style id, title and role", func() {
// style is overridden to checklist on ul, but div keeps it (asciidoctor compat)
source := `.mytitle
[#foo]
[disc.myrole]
* [x] item 1
* [x] item 2`
expected := `<div id="foo" class="ulist checklist disc myrole">
<div class="title">mytitle</div>
<ul class="checklist">
<li>
<p>&#10003; item 1</p>
</li>
<li>
<p>&#10003; item 2</p>
</li>
</ul>
</div>`
Expect(RenderHTML(source)).To(MatchHTML(expected))
})

It("parent checklist with title and nested checklist", func() {
source := `.Checklist
* [ ] parent not checked
Expand Down
2 changes: 2 additions & 0 deletions pkg/renderer/sgml/unordered_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func (r *sgmlRenderer) renderUnorderedList(ctx *renderer.Context, l types.Unorde
ID sanitized
Title sanitized
Roles sanitized
Style sanitized
Checklist bool
Items []types.UnorderedListItem
Content sanitized
Expand All @@ -42,6 +43,7 @@ func (r *sgmlRenderer) renderUnorderedList(ctx *renderer.Context, l types.Unorde
Items: l.Items,
Content: sanitized(content.String()),
Roles: r.renderElementRoles(l.Attributes),
Style: r.renderElementStyle(l.Attributes),
})
if err != nil {
return "", errors.Wrap(err, "unable to render unordered list")
Expand Down
41 changes: 41 additions & 0 deletions pkg/renderer/sgml/xhtml5/unordered_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,26 @@ and a standalone paragraph`
Expect(RenderXHTML(source)).To(MatchHTML(expected))
})

It("simple unordered list with style id, title and role", func() {
source := `.mytitle
[#foo]
[disc.myrole]
* item 1
* item 2`
expected := `<div id="foo" class="ulist disc myrole">
<div class="title">mytitle</div>
<ul class="disc">
<li>
<p>item 1</p>
</li>
<li>
<p>item 2</p>
</li>
</ul>
</div>`
Expect(RenderXHTML(source)).To(MatchHTML(expected))
})

It("simple unordered list with continuation", func() {
source := `* item 1
+
Expand Down Expand Up @@ -273,6 +293,27 @@ var _ = Describe("checklists", func() {
Expect(RenderXHTML(source)).To(MatchHTML(expected))
})

It("simple checklist with style id, title and role", func() {
// style is overridden to checklist on ul, but div keeps it (asciidoctor compat)
source := `.mytitle
[#foo]
[disc.myrole]
* [x] item 1
* [x] item 2`
expected := `<div id="foo" class="ulist checklist disc myrole">
<div class="title">mytitle</div>
<ul class="checklist">
<li>
<p>&#10003; item 1</p>
</li>
<li>
<p>&#10003; item 2</p>
</li>
</ul>
</div>`
Expect(RenderXHTML(source)).To(MatchHTML(expected))
})

It("parent checklist with title and nested checklist", func() {
source := `.Checklist
* [ ] parent not checked
Expand Down

0 comments on commit c93bc82

Please sign in to comment.