95 lines
1.8 KiB
Go
95 lines
1.8 KiB
Go
package element
|
|
|
|
import (
|
|
"time"
|
|
|
|
"ewintr.nl/adoc/token"
|
|
)
|
|
|
|
type Header struct {
|
|
Title string
|
|
Author string
|
|
Date time.Time
|
|
Attributes map[string]string
|
|
}
|
|
|
|
func (h Header) Text() string { return h.Title }
|
|
func (h Header) Append(_ []Element) Element { return h }
|
|
|
|
func NewHeaderFromTokens(tr ReadUnreader) (ParseResult, bool) {
|
|
toks, ok := tr.Read(2)
|
|
if !ok {
|
|
return ParseResult{}, false
|
|
}
|
|
if !toks[0].Equal(token.Token{Type: token.TYPE_EQUALSIGN, Literal: "="}) {
|
|
tr.Unread(2)
|
|
return ParseResult{}, false
|
|
}
|
|
if toks[1].Type != token.TYPE_WHITESPACE {
|
|
tr.Unread(2)
|
|
return ParseResult{}, false
|
|
}
|
|
for {
|
|
ntoks, ok := tr.Read(1)
|
|
if !ok {
|
|
tr.Unread(len(toks))
|
|
return ParseResult{}, false
|
|
}
|
|
if ntoks[0].Equal(token.TOKEN_EOF, token.TOKEN_DOUBLE_NEWLINE) {
|
|
break
|
|
}
|
|
toks = append(toks, ntoks[0])
|
|
}
|
|
|
|
h := &Header{
|
|
Attributes: map[string]string{},
|
|
}
|
|
lines := token.Split(toks[2:], token.TYPE_NEWLINE)
|
|
h.Title = token.Literals(lines[0])
|
|
|
|
for _, line := range lines[1:] {
|
|
switch {
|
|
case tryHeaderDate(h, line):
|
|
continue
|
|
case tryHeaderField(h, line):
|
|
continue
|
|
default:
|
|
h.Author = token.Literals(line)
|
|
}
|
|
}
|
|
|
|
return ParseResult{
|
|
Element: *h,
|
|
Inner: []token.Token{},
|
|
}, true
|
|
}
|
|
|
|
func tryHeaderField(h *Header, line []token.Token) bool {
|
|
if len(line) < 4 {
|
|
return false
|
|
}
|
|
pair := token.Split(line, token.TYPE_WHITESPACE)
|
|
if len(pair) != 2 {
|
|
return false
|
|
}
|
|
key, value := pair[0], pair[1]
|
|
|
|
if !token.HasPattern(key, []token.TokenType{token.TYPE_COLON, token.TYPE_WORD, token.TYPE_COLON}) {
|
|
return false
|
|
}
|
|
|
|
h.Attributes[key[1].Literal] = token.Literals(value)
|
|
|
|
return true
|
|
}
|
|
|
|
func tryHeaderDate(h *Header, line []token.Token) bool {
|
|
date, err := time.Parse("2006-01-02", token.Literals(line))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
h.Date = date
|
|
|
|
return true
|
|
}
|