mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update inline parser
This commit is contained in:
@ -18,8 +18,8 @@ type Bold struct {
|
||||
BaseInline
|
||||
|
||||
// Symbol is "*" or "_".
|
||||
Symbol string
|
||||
Content string
|
||||
Symbol string
|
||||
Children []Node
|
||||
}
|
||||
|
||||
func (*Bold) Type() NodeType {
|
||||
|
@ -53,8 +53,12 @@ func (p *BoldParser) Parse(tokens []*tokenizer.Token) (ast.Node, error) {
|
||||
|
||||
prefixTokenType := tokens[0].Type
|
||||
contentTokens := tokens[2 : size-2]
|
||||
children, err := ParseInlineWithParsers(contentTokens, []InlineParser{NewLinkParser(), NewTextParser()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ast.Bold{
|
||||
Symbol: prefixTokenType,
|
||||
Content: tokenizer.Stringify(contentTokens),
|
||||
Symbol: prefixTokenType,
|
||||
Children: children,
|
||||
}, nil
|
||||
}
|
||||
|
@ -21,15 +21,23 @@ func TestBoldParser(t *testing.T) {
|
||||
{
|
||||
text: "**Hello**",
|
||||
bold: &ast.Bold{
|
||||
Symbol: "*",
|
||||
Content: "Hello",
|
||||
Symbol: "*",
|
||||
Children: []ast.Node{
|
||||
&ast.Text{
|
||||
Content: "Hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "** Hello **",
|
||||
bold: &ast.Bold{
|
||||
Symbol: "*",
|
||||
Content: " Hello ",
|
||||
Symbol: "*",
|
||||
Children: []ast.Node{
|
||||
&ast.Text{
|
||||
Content: " Hello ",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -63,8 +63,12 @@ Hello World`,
|
||||
Level: 3,
|
||||
Children: []ast.Node{
|
||||
&ast.Bold{
|
||||
Symbol: "*",
|
||||
Content: "Hello",
|
||||
Symbol: "*",
|
||||
Children: []ast.Node{
|
||||
&ast.Text{
|
||||
Content: "Hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.Text{
|
||||
Content: " World",
|
||||
|
@ -29,6 +29,13 @@ func TestLinkParser(t *testing.T) {
|
||||
text: "[alte]( htt ps :/ /example.com)",
|
||||
link: nil,
|
||||
},
|
||||
{
|
||||
text: "[your/slash](https://example.com)",
|
||||
link: &ast.Link{
|
||||
Text: "your/slash",
|
||||
URL: "https://example.com",
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "[hello world](https://example.com)",
|
||||
link: &ast.Link{
|
||||
|
@ -76,10 +76,14 @@ var defaultInlineParsers = []InlineParser{
|
||||
}
|
||||
|
||||
func ParseInline(tokens []*tokenizer.Token) ([]ast.Node, error) {
|
||||
return ParseInlineWithParsers(tokens, defaultInlineParsers)
|
||||
}
|
||||
|
||||
func ParseInlineWithParsers(tokens []*tokenizer.Token, inlineParsers []InlineParser) ([]ast.Node, error) {
|
||||
nodes := []ast.Node{}
|
||||
var prevNode ast.Node
|
||||
for len(tokens) > 0 {
|
||||
for _, inlineParser := range defaultInlineParsers {
|
||||
for _, inlineParser := range inlineParsers {
|
||||
size, matched := inlineParser.Match(tokens)
|
||||
if matched {
|
||||
node, err := inlineParser.Parse(tokens)
|
||||
|
@ -32,8 +32,12 @@ func TestParser(t *testing.T) {
|
||||
&ast.Paragraph{
|
||||
Children: []ast.Node{
|
||||
&ast.Bold{
|
||||
Symbol: "*",
|
||||
Content: "Hello",
|
||||
Symbol: "*",
|
||||
Children: []ast.Node{
|
||||
&ast.Text{
|
||||
Content: "Hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.Text{
|
||||
Content: " world!",
|
||||
@ -51,8 +55,12 @@ func TestParser(t *testing.T) {
|
||||
Content: "Hello ",
|
||||
},
|
||||
&ast.Bold{
|
||||
Symbol: "*",
|
||||
Content: "world",
|
||||
Symbol: "*",
|
||||
Children: []ast.Node{
|
||||
&ast.Text{
|
||||
Content: "world",
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.Text{
|
||||
Content: "!",
|
||||
@ -78,8 +86,12 @@ func TestParser(t *testing.T) {
|
||||
Content: "Hello ",
|
||||
},
|
||||
&ast.Bold{
|
||||
Symbol: "*",
|
||||
Content: "world",
|
||||
Symbol: "*",
|
||||
Children: []ast.Node{
|
||||
&ast.Text{
|
||||
Content: "world",
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.Text{
|
||||
Content: "!",
|
||||
@ -150,7 +162,7 @@ func StringifyNode(node ast.Node) string {
|
||||
case *ast.Text:
|
||||
return "Text(" + n.Content + ")"
|
||||
case *ast.Bold:
|
||||
return "Bold(" + n.Symbol + n.Content + n.Symbol + ")"
|
||||
return "Bold(" + n.Symbol + StringifyNodes(n.Children) + n.Symbol + ")"
|
||||
case *ast.Italic:
|
||||
return "Italic(" + n.Symbol + n.Content + n.Symbol + ")"
|
||||
case *ast.BoldItalic:
|
||||
|
@ -35,8 +35,12 @@ func TestUnorderedListParser(t *testing.T) {
|
||||
Symbol: tokenizer.Asterisk,
|
||||
Children: []ast.Node{
|
||||
&ast.Bold{
|
||||
Symbol: "*",
|
||||
Content: "Hello",
|
||||
Symbol: "*",
|
||||
Children: []ast.Node{
|
||||
&ast.Text{
|
||||
Content: "Hello",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -149,7 +149,7 @@ func (r *HTMLRender) renderText(node *ast.Text) {
|
||||
|
||||
func (r *HTMLRender) renderBold(node *ast.Bold) {
|
||||
r.output.WriteString("<strong>")
|
||||
r.output.WriteString(node.Content)
|
||||
r.RenderNodes(node.Children)
|
||||
r.output.WriteString("</strong>")
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ func (r *StringRender) renderText(node *ast.Text) {
|
||||
}
|
||||
|
||||
func (r *StringRender) renderBold(node *ast.Bold) {
|
||||
r.output.WriteString(node.Content)
|
||||
r.RenderNodes(node.Children)
|
||||
}
|
||||
|
||||
func (r *StringRender) renderItalic(node *ast.Italic) {
|
||||
@ -151,12 +151,12 @@ func (r *StringRender) renderCode(node *ast.Code) {
|
||||
r.output.WriteString("`")
|
||||
}
|
||||
|
||||
func (*StringRender) renderImage(*ast.Image) {
|
||||
// Do nothing.
|
||||
func (r *StringRender) renderImage(node *ast.Image) {
|
||||
r.output.WriteString(node.AltText)
|
||||
}
|
||||
|
||||
func (*StringRender) renderLink(*ast.Link) {
|
||||
// Do nothing.
|
||||
func (r *StringRender) renderLink(node *ast.Link) {
|
||||
r.output.WriteString(node.Text)
|
||||
}
|
||||
|
||||
func (r *StringRender) renderTag(node *ast.Tag) {
|
||||
|
@ -22,6 +22,10 @@ func TestStringRender(t *testing.T) {
|
||||
text: "**Hello** world!",
|
||||
expected: `Hello world!`,
|
||||
},
|
||||
{
|
||||
text: "**[your/slash](https://example.com)** world!",
|
||||
expected: `your/slash world!`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
@ -1,45 +0,0 @@
|
||||
INSERT INTO
|
||||
user (
|
||||
`id`,
|
||||
`username`,
|
||||
`role`,
|
||||
`email`,
|
||||
`nickname`,
|
||||
`row_status`,
|
||||
`avatar_url`,
|
||||
`password_hash`
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
101,
|
||||
'memos-demo',
|
||||
'HOST',
|
||||
'demo@usememos.com',
|
||||
'Derobot',
|
||||
'NORMAL',
|
||||
'',
|
||||
-- raw password: secret
|
||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
||||
),
|
||||
(
|
||||
102,
|
||||
'jack',
|
||||
'USER',
|
||||
'jack@usememos.com',
|
||||
'Jack',
|
||||
'NORMAL',
|
||||
'',
|
||||
-- raw password: secret
|
||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
||||
),
|
||||
(
|
||||
103,
|
||||
'bob',
|
||||
'USER',
|
||||
'bob@usememos.com',
|
||||
'Bob',
|
||||
'ARCHIVED',
|
||||
'',
|
||||
-- raw password: secret
|
||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
||||
);
|
@ -1,51 +0,0 @@
|
||||
INSERT INTO
|
||||
memo (`id`, `content`, `creator_id`)
|
||||
VALUES
|
||||
(
|
||||
1,
|
||||
"#Hello 👋 Welcome to memos.",
|
||||
101
|
||||
);
|
||||
|
||||
INSERT INTO
|
||||
memo (
|
||||
`id`,
|
||||
`content`,
|
||||
`creator_id`,
|
||||
`visibility`
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
2,
|
||||
'#TODO
|
||||
- [x] Take more photos about **🌄 sunset**
|
||||
- [x] Clean the room
|
||||
- [ ] Read *📖 The Little Prince*
|
||||
(👆 click to toggle status)',
|
||||
101,
|
||||
'PROTECTED'
|
||||
),
|
||||
(
|
||||
3,
|
||||
"**[Slash](https://github.com/yourselfhosted/slash)**: A bookmarking and url shortener, save and share your links very easily.
|
||||
**[SQL Chat](https://www.sqlchat.ai)**: Chat-based SQL Client",
|
||||
101,
|
||||
'PUBLIC'
|
||||
),
|
||||
(
|
||||
4,
|
||||
'#TODO
|
||||
- [x] Take more photos about **🌄 sunset**
|
||||
- [ ] Clean the classroom
|
||||
- [ ] Watch *👦 The Boys*
|
||||
(👆 click to toggle status)
|
||||
',
|
||||
102,
|
||||
'PROTECTED'
|
||||
),
|
||||
(
|
||||
5,
|
||||
'三人行,必有我师焉!👨🏫',
|
||||
102,
|
||||
'PUBLIC'
|
||||
);
|
@ -1,5 +0,0 @@
|
||||
INSERT INTO
|
||||
memo_organizer (`memo_id`, `user_id`, `pinned`)
|
||||
VALUES
|
||||
(1, 101, 1),
|
||||
(3, 101, 1);
|
@ -1,6 +0,0 @@
|
||||
INSERT INTO
|
||||
tag (`name`, `creator_id`)
|
||||
VALUES
|
||||
('Hello', 101),
|
||||
('TODO', 101),
|
||||
('TODO', 102);
|
@ -1,44 +0,0 @@
|
||||
INSERT INTO "user" (
|
||||
id,
|
||||
username,
|
||||
role,
|
||||
email,
|
||||
nickname,
|
||||
row_status,
|
||||
avatar_url,
|
||||
password_hash
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
101,
|
||||
'memos-demo',
|
||||
'HOST',
|
||||
'demo@usememos.com',
|
||||
'Derobot',
|
||||
'NORMAL',
|
||||
'',
|
||||
-- raw password: secret
|
||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
||||
),
|
||||
(
|
||||
102,
|
||||
'jack',
|
||||
'USER',
|
||||
'jack@usememos.com',
|
||||
'Jack',
|
||||
'NORMAL',
|
||||
'',
|
||||
-- raw password: secret
|
||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
||||
),
|
||||
(
|
||||
103,
|
||||
'bob',
|
||||
'USER',
|
||||
'bob@usememos.com',
|
||||
'Bob',
|
||||
'ARCHIVED',
|
||||
'',
|
||||
-- raw password: secret
|
||||
'$2a$14$ajq8Q7fbtFRQvXpdCq7Jcuy.Rx1h/L4J60Otx.gyNLbAYctGMJ9tK'
|
||||
);
|
@ -1,34 +0,0 @@
|
||||
INSERT INTO memo (id, content, creator_id)
|
||||
VALUES
|
||||
(
|
||||
1,
|
||||
'#Hello 👋 Welcome to memos.',
|
||||
101
|
||||
);
|
||||
|
||||
INSERT INTO memo (id, content, creator_id, visibility)
|
||||
VALUES
|
||||
(
|
||||
2,
|
||||
E'#TODO\n- [x] Take more photos about **🌄 sunset**\n- [x] Clean the room\n- [ ] Read *📖 The Little Prince*\n(👆 click to toggle status)',
|
||||
101,
|
||||
'PROTECTED'
|
||||
),
|
||||
(
|
||||
3,
|
||||
E'**[Slash](https://github.com/yourselfhosted/slash)**: A bookmarking and url shortener, save and share your links very easily.\n**[SQL Chat](https://www.sqlchat.ai)**: Chat-based SQL Client',
|
||||
101,
|
||||
'PUBLIC'
|
||||
),
|
||||
(
|
||||
4,
|
||||
E'#TODO\n- [x] Take more photos about **🌄 sunset**\n- [ ] Clean the classroom\n- [ ] Watch *👦 The Boys*\n(👆 click to toggle status)',
|
||||
102,
|
||||
'PROTECTED'
|
||||
),
|
||||
(
|
||||
5,
|
||||
'三人行,必有我师焉!👨🏫',
|
||||
102,
|
||||
'PUBLIC'
|
||||
);
|
@ -1,5 +0,0 @@
|
||||
INSERT INTO
|
||||
memo_organizer (memo_id, user_id, pinned)
|
||||
VALUES
|
||||
(1, 101, 1),
|
||||
(3, 101, 1);
|
@ -1,6 +0,0 @@
|
||||
INSERT INTO
|
||||
tag (name, creator_id)
|
||||
VALUES
|
||||
('Hello', 101),
|
||||
('TODO', 101),
|
||||
('TODO', 102);
|
Reference in New Issue
Block a user