From 7da1555c847edfc5a1d75b1ed26362901d3f9609 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 21 Apr 2018 20:19:43 +0300 Subject: [PATCH] Improve Markdown rendering * Remove paragraphs from output HTML * Remove mention link wrapper from text (leaving only mention name) --- lib/bfhtml/doc.go | 2 ++ lib/bfhtml/html.go | 34 ++++++++++++++++++++++++++++++++++ matrix/matrix.go | 35 ++++++++++++++++++++++++++++++++++- ui/room-view.go | 5 +---- 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 lib/bfhtml/doc.go create mode 100644 lib/bfhtml/html.go diff --git a/lib/bfhtml/doc.go b/lib/bfhtml/doc.go new file mode 100644 index 0000000..4881087 --- /dev/null +++ b/lib/bfhtml/doc.go @@ -0,0 +1,2 @@ +// Package bfhtml contains an extension to the Blackfriday HTML renderer to disable paragraph tags. +package bfhtml diff --git a/lib/bfhtml/html.go b/lib/bfhtml/html.go new file mode 100644 index 0000000..14076ee --- /dev/null +++ b/lib/bfhtml/html.go @@ -0,0 +1,34 @@ +// gomuks - A terminal Matrix client written in Go. +// Copyright (C) 2018 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package bfhtml + +import ( + "io" + + bf "gopkg.in/russross/blackfriday.v2" +) + +type HTMLRenderer struct { + *bf.HTMLRenderer +} + +func (r *HTMLRenderer) RenderNode(w io.Writer, node *bf.Node, entering bool) bf.WalkStatus { + if node.Type == bf.Paragraph { + return bf.GoToNext + } + return r.HTMLRenderer.RenderNode(w, node, entering) +} diff --git a/matrix/matrix.go b/matrix/matrix.go index a38b439..eb0eea5 100644 --- a/matrix/matrix.go +++ b/matrix/matrix.go @@ -36,6 +36,7 @@ import ( "maunium.net/go/gomuks/config" "maunium.net/go/gomuks/debug" "maunium.net/go/gomuks/interface" + "maunium.net/go/gomuks/lib/bfhtml" "maunium.net/go/gomuks/matrix/pushrules" "maunium.net/go/gomuks/matrix/rooms" ) @@ -327,14 +328,46 @@ func (c *Container) SendMessage(roomID, msgtype, text string) (string, error) { return resp.EventID, nil } +func (c *Container) RenderMarkdown(text string) string { + parser := blackfriday.New( + blackfriday.WithExtensions(blackfriday.NoIntraEmphasis | + blackfriday.Tables | + blackfriday.FencedCode | + blackfriday.Strikethrough | + blackfriday.SpaceHeadings | + blackfriday.DefinitionLists)) + ast := parser.Parse([]byte(text)) + + renderer := bfhtml.HTMLRenderer{ + HTMLRenderer: blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{ + Flags: blackfriday.UseXHTML, + }), + } + + var buf strings.Builder + renderer.RenderHeader(&buf, ast) + ast.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + return renderer.RenderNode(&buf, node, entering) + }) + renderer.RenderFooter(&buf, ast) + return buf.String() +} + +var mentionRegex = regexp.MustCompile("\\[(.+?)]\\(https://matrix.to/#/@.+?:.+?\\)") +var roomRegex = regexp.MustCompile("\\[.+?]\\(https://matrix.to/#/(#.+?:[^/]+?)\\)") + func (c *Container) SendMarkdownMessage(roomID, msgtype, text string) (string, error) { defer debug.Recover() - html := string(blackfriday.Run([]byte(text))) + html := c.RenderMarkdown(text) if html == text { return c.SendMessage(roomID, msgtype, text) } + // Remove markdown link stuff from plaintext mentions and room links + text = mentionRegex.ReplaceAllString(text, "$1") + text = roomRegex.ReplaceAllString(text, "$1") + c.SendTyping(roomID, false) resp, err := c.client.SendMessageEvent(roomID, "m.room.message", map[string]interface{}{ diff --git a/ui/room-view.go b/ui/room-view.go index 332605b..a66b0ee 100644 --- a/ui/room-view.go +++ b/ui/room-view.go @@ -242,10 +242,7 @@ type completion struct { } func (view *RoomView) AutocompleteUser(existingText string) (completions []completion) { - textWithoutPrefix := existingText - if strings.HasPrefix(existingText, "@") { - textWithoutPrefix = existingText[1:] - } + textWithoutPrefix := strings.TrimPrefix(existingText, "@") for _, user := range view.Room.GetMembers() { if user.DisplayName == textWithoutPrefix || user.UserID == existingText { // Exact match, return that.