adoc/element/header.go

95 lines
1.8 KiB
Go
Raw Normal View History

2022-03-15 15:16:15 +01:00
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
}