@@ -4,14 +4,16 @@ import (
4
4
"fmt"
5
5
"strings"
6
6
7
+ "github.com/xnacly/fleck/cli"
7
8
"github.com/xnacly/fleck/logger"
8
9
"github.com/xnacly/fleck/scanner"
9
10
)
10
11
11
12
type Parser struct {
12
- tokens []scanner.Token
13
- tags []Tag
14
- current int
13
+ tokens []scanner.Token
14
+ tags []Tag
15
+ current int
16
+ headings []Heading
15
17
}
16
18
17
19
func New (tokens []scanner.Token ) Parser {
@@ -32,8 +34,9 @@ func (p *Parser) Parse() []Tag {
32
34
}
33
35
34
36
func (p * Parser ) tag () Tag {
35
- // parse headings just before paragraphs at the end, everything else before
36
- if p .peek ().Kind == scanner .HASH && (p .prev ().Kind == scanner .NEWLINE || p .prev ().Kind == 0 ) {
37
+ if p .check (scanner .BACKTICK ) {
38
+ return p .code ()
39
+ } else if p .check (scanner .HASH ) && (p .prev ().Kind == scanner .NEWLINE || p .prev ().Kind == 0 ) {
37
40
return p .heading ()
38
41
} else {
39
42
// TODO: currently skips everything except headings, fix that, this here is a temp messuare to keep the program from endless looping
@@ -42,15 +45,63 @@ func (p *Parser) tag() Tag {
42
45
}
43
46
}
44
47
48
+ func (p * Parser ) code () Tag {
49
+ p .advance ()
50
+ if p .check (scanner .TEXT ) {
51
+ // skip the `
52
+ p .advance ()
53
+ if p .check (scanner .BACKTICK ) {
54
+ return CodeInline {
55
+ text : p .prev ().Value ,
56
+ }
57
+ }
58
+ } else if p .check (scanner .BACKTICK ) {
59
+ p .advance ()
60
+ if ! p .check (scanner .BACKTICK ) {
61
+ return CodeInline {
62
+ text : "" ,
63
+ }
64
+ }
65
+ p .advance ()
66
+ language := p .peek ().Value
67
+ // skip lang definition
68
+ p .advance ()
69
+ // skip newline
70
+ p .advance ()
71
+
72
+ b := strings.Builder {}
73
+ for ! p .check (scanner .BACKTICK ) {
74
+ if p .check (scanner .TEXT ) {
75
+ b .WriteString (p .peek ().Value )
76
+ } else {
77
+ b .WriteRune (scanner .TOKEN_SYMBOL_MAP [p .peek ().Kind ])
78
+ }
79
+ p .advance ()
80
+ }
81
+
82
+ // skip the three ```
83
+ p .advance ()
84
+ p .advance ()
85
+ p .advance ()
86
+
87
+ return CodeBlock {
88
+ language : language ,
89
+ text : b .String (),
90
+ }
91
+ }
92
+ return nil
93
+ }
94
+
45
95
func (p * Parser ) paragraph () Tag {
46
96
return Paragraph {}
47
97
}
48
98
99
+ // TODO: find a way to parse the rest of the tokens as well, not just write them to the heading
49
100
func (p * Parser ) heading () Tag {
50
101
var lvl uint = 0
51
102
children := make ([]scanner.Token , 0 )
52
103
53
- for p .peek (). Kind == scanner .HASH {
104
+ for p .check ( scanner .HASH ) {
54
105
lvl ++
55
106
p .advance ()
56
107
}
@@ -60,6 +111,7 @@ func (p *Parser) heading() Tag {
60
111
p .advance ()
61
112
}
62
113
114
+ // skip the newline
63
115
p .advance ()
64
116
65
117
b := strings.Builder {}
@@ -74,11 +126,38 @@ func (p *Parser) heading() Tag {
74
126
b .WriteRune (scanner .TOKEN_SYMBOL_MAP [c .Kind ])
75
127
}
76
128
}
77
-
78
- return Heading {
129
+ heading := Heading {
79
130
lvl : lvl ,
80
131
text : b .String (),
81
132
}
133
+
134
+ if cli .GetFlag (cli .ARGUMENTS , "toc" ) {
135
+ p .headings = append (p .headings , heading )
136
+ }
137
+ return heading
138
+ }
139
+
140
+ func (p * Parser ) GenerateToc () string {
141
+ headingMap := map [uint ]uint {
142
+ 1 : 0 ,
143
+ 2 : 0 ,
144
+ 3 : 0 ,
145
+ }
146
+
147
+ b := strings.Builder {}
148
+ b .WriteString ("<h3>Table of contents</h3>" )
149
+ b .WriteString ("<ul>" )
150
+ for _ , v := range p .headings {
151
+ // TODO: make this a -toc-level=x flag
152
+ // TODO: switch over levels, indent subheadings using <ul> in <ul>
153
+ if v .lvl > 3 {
154
+ continue
155
+ }
156
+ headingMap [v .lvl ]++
157
+ b .WriteString (fmt .Sprintf ("<li><a href=\" #%s\" >%d.%d.%d</a>: %s</li>" , v .text , headingMap [1 ], headingMap [2 ], headingMap [3 ], v .text ))
158
+ }
159
+ b .WriteString ("</ul>" )
160
+ return b .String ()
82
161
}
83
162
84
163
func (p * Parser ) match (types ... uint ) bool {
0 commit comments