aboutsummaryrefslogtreecommitdiff
path: root/ui/messages/html
diff options
context:
space:
mode:
Diffstat (limited to 'ui/messages/html')
-rw-r--r--ui/messages/html/blockquote.go32
-rw-r--r--ui/messages/html/break.go12
-rw-r--r--ui/messages/html/codeblock.go7
-rw-r--r--ui/messages/html/entity.go11
-rw-r--r--ui/messages/html/horizontalline.go56
-rw-r--r--ui/messages/html/list.go33
-rw-r--r--ui/messages/html/parser.go10
7 files changed, 154 insertions, 7 deletions
diff --git a/ui/messages/html/blockquote.go b/ui/messages/html/blockquote.go
index 30ce52e..17799a2 100644
--- a/ui/messages/html/blockquote.go
+++ b/ui/messages/html/blockquote.go
@@ -18,6 +18,7 @@ package html
import (
"fmt"
+ "strings"
"maunium.net/go/mauview"
)
@@ -37,6 +38,10 @@ func NewBlockquoteEntity(children []Entity) *BlockquoteEntity {
}}
}
+func (be *BlockquoteEntity) Clone() Entity {
+ return &BlockquoteEntity{BaseEntity: be.BaseEntity.Clone().(*BaseEntity)}
+}
+
func (be *BlockquoteEntity) Draw(screen mauview.Screen) {
be.BaseEntity.Draw(screen)
for y := 0; y < be.height; y++ {
@@ -44,6 +49,33 @@ func (be *BlockquoteEntity) Draw(screen mauview.Screen) {
}
}
+func (be *BlockquoteEntity) PlainText() string {
+ if len(be.Children) == 0 {
+ return ""
+ }
+ var buf strings.Builder
+ newlined := false
+ for i, child := range be.Children {
+ if i != 0 && child.IsBlock() && !newlined {
+ buf.WriteRune('\n')
+ }
+ newlined = false
+ for i, row := range strings.Split(child.PlainText(), "\n") {
+ if i != 0 {
+ buf.WriteRune('\n')
+ }
+ buf.WriteRune('>')
+ buf.WriteRune(' ')
+ buf.WriteString(row)
+ }
+ if child.IsBlock() {
+ buf.WriteRune('\n')
+ newlined = true
+ }
+ }
+ return strings.TrimSpace(buf.String())
+}
+
func (be *BlockquoteEntity) String() string {
return fmt.Sprintf("&html.BlockquoteEntity{%s},\n", be.BaseEntity)
}
diff --git a/ui/messages/html/break.go b/ui/messages/html/break.go
index d400f00..ea67ead 100644
--- a/ui/messages/html/break.go
+++ b/ui/messages/html/break.go
@@ -26,3 +26,15 @@ func NewBreakEntity() *BreakEntity {
Block: true,
}}
}
+
+func (be *BreakEntity) Clone() Entity {
+ return NewBreakEntity()
+}
+
+func (be *BreakEntity) PlainText() string {
+ return "\n"
+}
+
+func (be *BreakEntity) String() string {
+ return "&html.BreakEntity{},\n"
+}
diff --git a/ui/messages/html/codeblock.go b/ui/messages/html/codeblock.go
index ec6181d..4a0766c 100644
--- a/ui/messages/html/codeblock.go
+++ b/ui/messages/html/codeblock.go
@@ -37,6 +37,13 @@ func NewCodeBlockEntity(children []Entity, background tcell.Style) *CodeBlockEnt
}
}
+func (ce *CodeBlockEntity) Clone() Entity {
+ return &CodeBlockEntity{
+ BaseEntity: ce.BaseEntity.Clone().(*BaseEntity),
+ Background: ce.Background,
+ }
+}
+
func (ce *CodeBlockEntity) Draw(screen mauview.Screen) {
screen.Fill(' ', ce.Background)
ce.BaseEntity.Draw(screen)
diff --git a/ui/messages/html/entity.go b/ui/messages/html/entity.go
index 2ce37a8..be58d61 100644
--- a/ui/messages/html/entity.go
+++ b/ui/messages/html/entity.go
@@ -165,17 +165,20 @@ func (he *BaseEntity) PlainText() string {
buf.WriteString(he.Text)
newlined := false
for _, child := range he.Children {
- if child.IsBlock() && !newlined {
+ text := child.PlainText()
+ if !strings.HasPrefix(text, "\n") && child.IsBlock() && !newlined {
buf.WriteRune('\n')
}
newlined = false
- buf.WriteString(child.PlainText())
+ buf.WriteString(text)
if child.IsBlock() {
- buf.WriteRune('\n')
+ if !strings.HasSuffix(text, "\n") {
+ buf.WriteRune('\n')
+ }
newlined = true
}
}
- return buf.String()
+ return strings.TrimSpace(buf.String())
}
// Draw draws this entity onto the given mauview Screen.
diff --git a/ui/messages/html/horizontalline.go b/ui/messages/html/horizontalline.go
new file mode 100644
index 0000000..32761aa
--- /dev/null
+++ b/ui/messages/html/horizontalline.go
@@ -0,0 +1,56 @@
+// gomuks - A terminal Matrix client written in Go.
+// Copyright (C) 2019 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero 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 Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+package html
+
+import (
+ "strings"
+
+ "maunium.net/go/mauview"
+)
+
+type HorizontalLineEntity struct {
+ *BaseEntity
+}
+
+const HorizontalLineChar = '━'
+
+func NewHorizontalLineEntity() *HorizontalLineEntity {
+ return &HorizontalLineEntity{&BaseEntity{
+ Tag: "hr",
+ Block: true,
+ DefaultHeight: 1,
+ }}
+}
+
+func (he *HorizontalLineEntity) Clone() Entity {
+ return NewHorizontalLineEntity()
+}
+
+func (he *HorizontalLineEntity) Draw(screen mauview.Screen) {
+ width, _ := screen.Size()
+ for x := 0; x < width; x++ {
+ screen.SetContent(x, 0, HorizontalLineChar, nil, he.Style)
+ }
+}
+
+func (he *HorizontalLineEntity) PlainText() string {
+ return strings.Repeat(string(HorizontalLineChar), 5)
+}
+
+func (he *HorizontalLineEntity) String() string {
+ return "&html.HorizontalLineEntity{},\n"
+}
diff --git a/ui/messages/html/list.go b/ui/messages/html/list.go
index 9f45b92..c611e66 100644
--- a/ui/messages/html/list.go
+++ b/ui/messages/html/list.go
@@ -56,6 +56,14 @@ func NewListEntity(ordered bool, start int, children []Entity) *ListEntity {
return entity
}
+func (le *ListEntity) Clone() Entity {
+ return &ListEntity{
+ BaseEntity: le.BaseEntity.Clone().(*BaseEntity),
+ Ordered: le.Ordered,
+ Start: le.Start,
+ }
+}
+
func (le *ListEntity) Draw(screen mauview.Screen) {
width, _ := screen.Size()
@@ -75,6 +83,31 @@ func (le *ListEntity) Draw(screen mauview.Screen) {
}
}
+func (le *ListEntity) PlainText() string {
+ if len(le.Children) == 0 {
+ return ""
+ }
+ var buf strings.Builder
+ for i, child := range le.Children {
+ indent := strings.Repeat(" ", le.Indent)
+ if le.Ordered {
+ number := le.Start + i
+ _, _ = fmt.Fprintf(&buf, "%d. %s", number, strings.Repeat(" ", le.Indent-2-digits(number)))
+ } else {
+ buf.WriteString("● ")
+ }
+ for j, row := range strings.Split(child.PlainText(), "\n") {
+ if j != 0 {
+ buf.WriteRune('\n')
+ buf.WriteString(indent)
+ }
+ buf.WriteString(row)
+ }
+ buf.WriteRune('\n')
+ }
+ return strings.TrimSpace(buf.String())
+}
+
func (le *ListEntity) String() string {
return fmt.Sprintf("&html.ListEntity{Ordered=%t, Start=%d, Base=%s},\n", le.Ordered, le.Start, le.BaseEntity)
}
diff --git a/ui/messages/html/parser.go b/ui/messages/html/parser.go
index 0bdf483..9e08ab7 100644
--- a/ui/messages/html/parser.go
+++ b/ui/messages/html/parser.go
@@ -111,7 +111,7 @@ func (parser *htmlParser) basicFormatToEntity(node *html.Node) Entity {
entity.AdjustStyle(AdjustStyleBold)
case "i", "em":
entity.AdjustStyle(AdjustStyleItalic)
- case "s", "del":
+ case "s", "del", "strike":
entity.AdjustStyle(AdjustStyleStrikethrough)
case "u", "ins":
entity.AdjustStyle(AdjustStyleUnderline)
@@ -237,7 +237,7 @@ func (parser *htmlParser) syntaxHighlight(text, language string) Entity {
children := make([]Entity, len(tokens))
for i, token := range tokens {
if token.Value == "\n" {
- children[i] = &BaseEntity{Block: true, Tag: "br"}
+ children[i] = NewBreakEntity()
} else {
children[i] = &BaseEntity{
Tag: token.Type.String(),
@@ -282,7 +282,7 @@ func (parser *htmlParser) tagNodeToEntity(node *html.Node) Entity {
return parser.headerToEntity(node)
case "br":
return NewBreakEntity()
- case "b", "strong", "i", "em", "s", "del", "u", "ins", "font":
+ case "b", "strong", "i", "em", "s", "strike", "del", "u", "ins", "font":
return parser.basicFormatToEntity(node)
case "a":
return parser.linkToEntity(node)
@@ -290,6 +290,10 @@ func (parser *htmlParser) tagNodeToEntity(node *html.Node) Entity {
return parser.imageToEntity(node)
case "pre":
return parser.codeblockToEntity(node)
+ case "hr":
+ return NewHorizontalLineEntity()
+ case "mx-reply":
+ return nil
default:
return &BaseEntity{
Tag: node.Data,