mirror of https://github.com/usememos/memos
parent
a07d5d38d6
commit
88799d469c
@ -0,0 +1,3 @@
|
|||||||
|
# gomark
|
||||||
|
|
||||||
|
A markdown parser for memos. WIP
|
@ -0,0 +1,19 @@
|
|||||||
|
package ast
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
Type string
|
||||||
|
Text string
|
||||||
|
Children []*Node
|
||||||
|
}
|
||||||
|
|
||||||
|
type Document struct {
|
||||||
|
Nodes []*Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDocument() *Document {
|
||||||
|
return &Document{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) AddNode(node *Node) {
|
||||||
|
d.Nodes = append(d.Nodes, node)
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package ast
|
||||||
|
|
||||||
|
func NewNode(tp, text string) *Node {
|
||||||
|
return &Node{
|
||||||
|
Type: tp,
|
||||||
|
Text: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) AddChild(child *Node) {
|
||||||
|
n.Children = append(n.Children, child)
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
package gomark
|
@ -0,0 +1,41 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/usememos/memos/plugin/gomark/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HeadingTokenizer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHeadingTokenizer() *HeadingTokenizer {
|
||||||
|
return &HeadingTokenizer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*HeadingTokenizer) Trigger() []byte {
|
||||||
|
return []byte{'#'}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*HeadingTokenizer) Parse(parent *ast.Node, block string) *ast.Node {
|
||||||
|
line := block
|
||||||
|
level := 0
|
||||||
|
for _, c := range line {
|
||||||
|
if c == '#' {
|
||||||
|
level++
|
||||||
|
} else if c == ' ' {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if level == 0 || level > 6 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
text := strings.TrimSpace(line[level+1:])
|
||||||
|
node := ast.NewNode("h1", text)
|
||||||
|
if parent != nil {
|
||||||
|
parent.AddChild(node)
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
package parser
|
@ -0,0 +1 @@
|
|||||||
|
package parser
|
@ -0,0 +1,27 @@
|
|||||||
|
package tokenizer
|
||||||
|
|
||||||
|
type TokenType = string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Underline TokenType = "_"
|
||||||
|
Star TokenType = "*"
|
||||||
|
Newline TokenType = "\n"
|
||||||
|
Hash TokenType = "#"
|
||||||
|
Space TokenType = " "
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Text TokenType = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
type Token struct {
|
||||||
|
Type TokenType
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewToken(tp, text string) *Token {
|
||||||
|
return &Token{
|
||||||
|
Type: tp,
|
||||||
|
Value: text,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package tokenizer
|
||||||
|
|
||||||
|
func tokenize(text string) []*Token {
|
||||||
|
tokens := []*Token{}
|
||||||
|
for _, c := range text {
|
||||||
|
switch c {
|
||||||
|
case '_':
|
||||||
|
tokens = append(tokens, NewToken(Underline, "_"))
|
||||||
|
case '*':
|
||||||
|
tokens = append(tokens, NewToken(Star, "*"))
|
||||||
|
case '\n':
|
||||||
|
tokens = append(tokens, NewToken(Newline, "\n"))
|
||||||
|
case ' ':
|
||||||
|
tokens = append(tokens, NewToken(Space, " "))
|
||||||
|
default:
|
||||||
|
var lastToken *Token
|
||||||
|
if len(tokens) > 0 {
|
||||||
|
lastToken = tokens[len(tokens)-1]
|
||||||
|
}
|
||||||
|
if lastToken == nil || lastToken.Type != Text {
|
||||||
|
tokens = append(tokens, NewToken(Text, string(c)))
|
||||||
|
} else {
|
||||||
|
lastToken.Value += string(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tokens
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package tokenizer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTokenize(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
text string
|
||||||
|
tokens []*Token
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
text: "*Hello world!",
|
||||||
|
tokens: []*Token{
|
||||||
|
{
|
||||||
|
Type: Star,
|
||||||
|
Value: "*",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Text,
|
||||||
|
Value: "Hello",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Space,
|
||||||
|
Value: " ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Text,
|
||||||
|
Value: "world!",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
result := tokenize(test.text)
|
||||||
|
require.Equal(t, test.tokens, result)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
package renderer
|
Loading…
Reference in New Issue