memos/plugin/gomark/parser/heading.go

77 lines
1.4 KiB
Go
Raw Normal View History

package parser
import (
2023-12-13 23:50:05 +08:00
"errors"
2023-12-13 09:06:47 +08:00
"github.com/usememos/memos/plugin/gomark/ast"
2023-05-23 19:52:31 +08:00
"github.com/usememos/memos/plugin/gomark/parser/tokenizer"
)
2023-12-13 09:06:47 +08:00
type HeadingParser struct{}
2023-05-23 20:49:32 +08:00
func NewHeadingParser() *HeadingParser {
return &HeadingParser{}
}
2023-12-13 09:06:47 +08:00
func (*HeadingParser) Match(tokens []*tokenizer.Token) (int, bool) {
2023-05-23 19:52:31 +08:00
cursor := 0
for _, token := range tokens {
if token.Type == tokenizer.Hash {
cursor++
} else {
2023-05-23 19:52:31 +08:00
break
}
}
2023-05-23 19:52:31 +08:00
if len(tokens) <= cursor+1 {
2023-12-13 09:06:47 +08:00
return 0, false
2023-05-23 19:52:31 +08:00
}
if tokens[cursor].Type != tokenizer.Space {
2023-12-13 09:06:47 +08:00
return 0, false
2023-05-23 19:52:31 +08:00
}
level := cursor
if level == 0 || level > 6 {
2023-12-13 09:06:47 +08:00
return 0, false
}
2023-05-23 19:52:31 +08:00
cursor++
contentTokens := []*tokenizer.Token{}
for _, token := range tokens[cursor:] {
if token.Type == tokenizer.Newline {
break
}
contentTokens = append(contentTokens, token)
2023-05-23 20:49:32 +08:00
cursor++
2023-05-23 19:52:31 +08:00
}
if len(contentTokens) == 0 {
2023-12-13 09:06:47 +08:00
return 0, false
}
return cursor, true
}
2023-12-13 23:50:05 +08:00
func (p *HeadingParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) {
2023-12-13 09:06:47 +08:00
size, ok := p.Match(tokens)
if size == 0 || !ok {
2023-12-13 23:50:05 +08:00
return nil, errors.New("not matched")
2023-05-23 19:52:31 +08:00
}
2023-12-13 09:06:47 +08:00
level := 0
for _, token := range tokens {
if token.Type == tokenizer.Hash {
level++
} else {
break
}
}
2023-12-13 23:50:05 +08:00
2023-12-13 09:06:47 +08:00
contentTokens := tokens[level+1 : size]
2023-12-14 00:24:41 +08:00
children, err := ParseInline(contentTokens)
2023-12-13 23:50:05 +08:00
if err != nil {
return nil, err
}
2023-12-14 00:24:41 +08:00
return &ast.Heading{
Level: level,
Children: children,
}, nil
}