memos/plugin/gomark/parser/heading.go
2023-12-13 23:50:05 +08:00

77 lines
1.4 KiB
Go

package parser
import (
"errors"
"github.com/usememos/memos/plugin/gomark/ast"
"github.com/usememos/memos/plugin/gomark/parser/tokenizer"
)
type HeadingParser struct{}
func NewHeadingParser() *HeadingParser {
return &HeadingParser{}
}
func (*HeadingParser) Match(tokens []*tokenizer.Token) (int, bool) {
cursor := 0
for _, token := range tokens {
if token.Type == tokenizer.Hash {
cursor++
} else {
break
}
}
if len(tokens) <= cursor+1 {
return 0, false
}
if tokens[cursor].Type != tokenizer.Space {
return 0, false
}
level := cursor
if level == 0 || level > 6 {
return 0, false
}
cursor++
contentTokens := []*tokenizer.Token{}
for _, token := range tokens[cursor:] {
if token.Type == tokenizer.Newline {
break
}
contentTokens = append(contentTokens, token)
cursor++
}
if len(contentTokens) == 0 {
return 0, false
}
return cursor, true
}
func (p *HeadingParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) {
size, ok := p.Match(tokens)
if size == 0 || !ok {
return nil, errors.New("not matched")
}
level := 0
for _, token := range tokens {
if token.Type == tokenizer.Hash {
level++
} else {
break
}
}
contentTokens := tokens[level+1 : size]
heading := &ast.Heading{
Level: level,
}
children, err := ParseInline(heading, contentTokens)
if err != nil {
return nil, err
}
heading.Children = children
return heading, nil
}