1package parser
2
3import (
4 "bytes"
5 "fmt"
6
7 "github.com/gomarkdown/markdown/ast"
8)
9
10// parse '(#r)', where r does not contain spaces. Or.
11// (!item) (!item, subitem), for an index, (!!item) signals primary.
12func maybeShortRefOrIndex(p *Parser, data []byte, offset int) (int, ast.Node) {
13 if len(data[offset:]) < 4 {
14 return 0, nil
15 }
16 // short ref first
17 data = data[offset:]
18 i := 1
19 switch data[i] {
20 case '#': // cross ref
21 i++
22 Loop:
23 for i < len(data) {
24 c := data[i]
25 switch {
26 case c == ')':
27 break Loop
28 case !isAlnum(c):
29 if c == '_' || c == '-' || c == ':' {
30 i++
31 continue
32 }
33 i = 0
34 break Loop
35 }
36 i++
37 }
38 if i >= len(data) {
39 return 0, nil
40 }
41 if data[i] != ')' {
42 return 0, nil
43 }
44
45 id := data[2:i]
46 node := &ast.CrossReference{}
47 node.Destination = id
48
49 return i + 1, node
50
51 case '!': // index
52 i++
53 start := i
54 i = skipUntilChar(data, start, ')')
55
56 // did we reach the end of the buffer without a closing marker?
57 if i >= len(data) {
58 return 0, nil
59 }
60
61 if len(data[start:i]) < 1 {
62 return 0, nil
63 }
64
65 idx := &ast.Index{}
66
67 idx.ID = fmt.Sprintf("idxref:%d", p.indexCnt)
68 p.indexCnt++
69
70 idx.Primary = data[start] == '!'
71 buf := data[start:i]
72
73 if idx.Primary {
74 buf = buf[1:]
75 }
76 items := bytes.Split(buf, []byte(","))
77 switch len(items) {
78 case 1:
79 idx.Item = bytes.TrimSpace(items[0])
80 return i + 1, idx
81 case 2:
82 idx.Item = bytes.TrimSpace(items[0])
83 idx.Subitem = bytes.TrimSpace(items[1])
84 return i + 1, idx
85 }
86 }
87
88 return 0, nil
89}