memos/plugin/gomark/parser/heading.go

74 lines
1.3 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-12-16 11:34:55 +08:00
level := 0
2023-05-23 19:52:31 +08:00
for _, token := range tokens {
2023-12-16 08:51:29 +08:00
if token.Type == tokenizer.PoundSign {
2023-12-16 11:34:55 +08:00
level++
} else {
2023-05-23 19:52:31 +08:00
break
}
}
2023-12-16 11:34:55 +08:00
if len(tokens) <= level+1 {
2023-12-13 09:06:47 +08:00
return 0, false
2023-05-23 19:52:31 +08:00
}
2023-12-16 11:34:55 +08:00
if tokens[level].Type != tokenizer.Space {
2023-12-13 09:06:47 +08:00
return 0, false
2023-05-23 19:52:31 +08:00
}
if level == 0 || level > 6 {
2023-12-13 09:06:47 +08:00
return 0, false
}
2023-05-23 19:52:31 +08:00
contentTokens := []*tokenizer.Token{}
2023-12-16 11:34:55 +08:00
for _, token := range tokens[level+1:] {
2023-05-23 19:52:31 +08:00
if token.Type == tokenizer.Newline {
break
}
2023-12-28 22:35:39 +08:00
contentTokens = append(contentTokens, token)
2023-05-23 19:52:31 +08:00
}
if len(contentTokens) == 0 {
2023-12-13 09:06:47 +08:00
return 0, false
}
2023-12-16 11:34:55 +08:00
return len(contentTokens) + level + 1, true
2023-12-13 09:06:47 +08:00
}
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 {
2023-12-16 08:51:29 +08:00
if token.Type == tokenizer.PoundSign {
2023-12-13 09:06:47 +08:00
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
}