Merge pull request #55 from mmarkdown/index-example-list
parser: allow indices
This commit is contained in:
commit
f5568e358d
|
@ -366,6 +366,15 @@ type Callout struct {
|
|||
ID []byte // number of this callout
|
||||
}
|
||||
|
||||
// Index is a node that contains an Index item and an optional, subitem.
|
||||
type Index struct {
|
||||
Leaf
|
||||
|
||||
Primary bool
|
||||
Item []byte
|
||||
Subitem []byte
|
||||
}
|
||||
|
||||
func removeNodeFromArray(a []Node, node Node) []Node {
|
||||
n := len(a)
|
||||
for i := 0; i < n; i++ {
|
||||
|
|
|
@ -869,6 +869,10 @@ func (r *Renderer) callout(w io.Writer, node *ast.Callout) {
|
|||
r.outs(w, "</span>")
|
||||
}
|
||||
|
||||
func (r *Renderer) index(w io.Writer, node *ast.Index) {
|
||||
// there is no in-text representation.
|
||||
}
|
||||
|
||||
// RenderNode renders a markdown node to HTML
|
||||
func (r *Renderer) RenderNode(w io.Writer, node ast.Node, entering bool) ast.WalkStatus {
|
||||
if r.opts.RenderNodeHook != nil {
|
||||
|
@ -957,6 +961,8 @@ func (r *Renderer) RenderNode(w io.Writer, node ast.Node, entering bool) ast.Wal
|
|||
r.matter(w, node, entering)
|
||||
case *ast.Callout:
|
||||
r.callout(w, node)
|
||||
case *ast.Index:
|
||||
r.index(w, node)
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown node %T", node))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package parser
|
||||
|
||||
import "github.com/gomarkdown/markdown/ast"
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
// parse '(#r)', where r does not contain spaces and is an existing label. Or.
|
||||
"github.com/gomarkdown/markdown/ast"
|
||||
)
|
||||
|
||||
// parse '(#r)', where r does not contain spaces. Or.
|
||||
// (!item) (!item, subitem), for an index, (!!item) signals primary.
|
||||
func maybeShortRefOrIndex(p *Parser, data []byte, offset int) (int, ast.Node) {
|
||||
if len(data[offset:]) < 4 {
|
||||
|
@ -11,9 +15,8 @@ func maybeShortRefOrIndex(p *Parser, data []byte, offset int) (int, ast.Node) {
|
|||
// short ref first
|
||||
data = data[offset:]
|
||||
i := 1
|
||||
if data[i] != '#' {
|
||||
return 0, nil
|
||||
}
|
||||
switch data[i] {
|
||||
case '#': // cross ref
|
||||
i++
|
||||
Loop:
|
||||
for i < len(data) {
|
||||
|
@ -41,4 +44,38 @@ Loop:
|
|||
node.Destination = id
|
||||
|
||||
return i, node
|
||||
|
||||
case '!': // index
|
||||
i++
|
||||
start := i
|
||||
i = skipUntilChar(data, start, ')')
|
||||
|
||||
// did we reach the end of the buffer without a closing marker?
|
||||
if i >= len(data) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(data[start:i]) < 1 {
|
||||
return 0, nil
|
||||
}
|
||||
idx := &ast.Index{}
|
||||
idx.Primary = data[start] == '!'
|
||||
buf := data[start:i]
|
||||
|
||||
if idx.Primary {
|
||||
buf = buf[1:]
|
||||
}
|
||||
items := bytes.Split(buf, []byte(","))
|
||||
switch len(items) {
|
||||
case 1:
|
||||
idx.Item = bytes.TrimSpace(items[0])
|
||||
return i + 1, idx
|
||||
case 2:
|
||||
idx.Item = bytes.TrimSpace(items[0])
|
||||
idx.Subitem = bytes.TrimSpace(items[1])
|
||||
return i + 1, idx
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
|
|
@ -36,3 +36,58 @@ func TestCrossReference(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndex(t *testing.T) {
|
||||
p := New()
|
||||
|
||||
tests := []struct {
|
||||
data []byte
|
||||
i *ast.Index
|
||||
fail bool
|
||||
}{
|
||||
// ok
|
||||
{
|
||||
data: []byte("(!yes)"),
|
||||
i: &ast.Index{Item: []byte("yes")},
|
||||
},
|
||||
{
|
||||
data: []byte("(!y:es)"),
|
||||
i: &ast.Index{Item: []byte("y:es")},
|
||||
},
|
||||
{
|
||||
data: []byte("(!yes, no)"),
|
||||
i: &ast.Index{Item: []byte("yes"), Subitem: []byte("no")},
|
||||
},
|
||||
{
|
||||
data: []byte("(! yes , no )"),
|
||||
i: &ast.Index{Item: []byte("yes"), Subitem: []byte("no")},
|
||||
},
|
||||
// fails
|
||||
{data: []byte("(!yes"), fail: true},
|
||||
{data: []byte("(_yes"), fail: true},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
_, n := maybeShortRefOrIndex(p, test.data, 0)
|
||||
if test.fail && n != nil {
|
||||
t.Errorf("test %d, should have failed to parse %s", i, test.data)
|
||||
continue
|
||||
}
|
||||
if test.fail && n == nil {
|
||||
// ok
|
||||
continue
|
||||
}
|
||||
|
||||
idx := n.(*ast.Index)
|
||||
|
||||
if string(test.i.Item) != string(idx.Item) {
|
||||
t.Errorf("test %d, got item %s, wanted %s", i, idx.Item, test.i.Item)
|
||||
}
|
||||
if string(test.i.Subitem) != string(idx.Subitem) {
|
||||
t.Errorf("test %d, got item %s, wanted %s", i, idx.Subitem, test.i.Subitem)
|
||||
}
|
||||
if test.i.Primary != idx.Primary {
|
||||
t.Errorf("test %d, got item %t, wanted %t", i, idx.Primary, test.i.Primary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,3 +79,14 @@ code
|
|||
---
|
||||
<pre><code class="myclass1 myclass2">code
|
||||
</code></pre>
|
||||
---
|
||||
# Index
|
||||
(!myitem, subitem)
|
||||
(!!item)
|
||||
(!!item, subtitem )
|
||||
---
|
||||
<h1>Index</h1>
|
||||
|
||||
<p>
|
||||
|
||||
</p>
|
||||
|
|
Loading…
Reference in New Issue