Fix non-syntax-highlighted code block newline rendering
This commit is contained in:
		@@ -474,29 +474,25 @@ func (view *MessageView) Draw(screen mauview.Screen) {
 | 
			
		||||
	scrollBarHeight, scrollBarPos := view.calculateScrollBar(view.height)
 | 
			
		||||
 | 
			
		||||
	var prevMeta ifc.MessageMeta
 | 
			
		||||
	firstLine := true
 | 
			
		||||
	skippedLines := 0
 | 
			
		||||
 | 
			
		||||
	for line := 0; line < view.height; line++ {
 | 
			
		||||
		index := indexOffset + line
 | 
			
		||||
		if index < 0 {
 | 
			
		||||
			skippedLines++
 | 
			
		||||
			continue
 | 
			
		||||
		} else if index >= view.TotalHeight() {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		showScrollbar := line-skippedLines >= scrollBarPos-scrollBarHeight && line-skippedLines < scrollBarPos
 | 
			
		||||
		isTop := firstLine && view.ScrollOffset+view.height >= view.TotalHeight()
 | 
			
		||||
	viewStart := 0
 | 
			
		||||
	if indexOffset < 0 {
 | 
			
		||||
		viewStart = -indexOffset
 | 
			
		||||
	}
 | 
			
		||||
	for line := viewStart; line < view.height; line++ {
 | 
			
		||||
		showScrollbar := line-viewStart >= scrollBarPos-scrollBarHeight && line-viewStart < scrollBarPos
 | 
			
		||||
		isTop := line == viewStart && view.ScrollOffset+view.height >= view.TotalHeight()
 | 
			
		||||
		isBottom := line == view.height-1 && view.ScrollOffset == 0
 | 
			
		||||
 | 
			
		||||
		borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
 | 
			
		||||
 | 
			
		||||
		firstLine = false
 | 
			
		||||
 | 
			
		||||
		if !bareMode {
 | 
			
		||||
			screen.SetContent(separatorX, line, borderChar, nil, borderStyle)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for line := viewStart; line < view.height && indexOffset+line < view.TotalHeight(); line++ {
 | 
			
		||||
		index := indexOffset + line
 | 
			
		||||
 | 
			
		||||
		text, meta := view.textBuffer[index], view.metaBuffer[index]
 | 
			
		||||
		if meta != prevMeta {
 | 
			
		||||
@@ -519,11 +515,6 @@ func (view *MessageView) Draw(screen mauview.Screen) {
 | 
			
		||||
				line--
 | 
			
		||||
			}
 | 
			
		||||
			message.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width-messageX, message.Height()))
 | 
			
		||||
			if !bareMode {
 | 
			
		||||
				for i := line; i < line+message.Height(); i++ {
 | 
			
		||||
					screen.SetContent(separatorX, i, borderChar, nil, borderStyle)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			line += message.Height() - 1
 | 
			
		||||
		} else {
 | 
			
		||||
			text.Draw(screen, messageX, line)
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,10 @@ type HTMLMessage struct {
 | 
			
		||||
	BaseMessage
 | 
			
		||||
 | 
			
		||||
	Root HTMLEntity
 | 
			
		||||
 | 
			
		||||
	FocusedBackground tcell.Color
 | 
			
		||||
 | 
			
		||||
	focused bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHTMLMessage(id, sender, displayname string, msgtype mautrix.MessageType, root HTMLEntity, timestamp time.Time) UIMessage {
 | 
			
		||||
@@ -45,9 +49,21 @@ func NewHTMLMessage(id, sender, displayname string, msgtype mautrix.MessageType,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (hw *HTMLMessage) Draw(screen mauview.Screen) {
 | 
			
		||||
	if hw.focused {
 | 
			
		||||
		screen.SetStyle(tcell.StyleDefault.Background(hw.FocusedBackground))
 | 
			
		||||
	}
 | 
			
		||||
	screen.Clear()
 | 
			
		||||
	hw.Root.Draw(screen)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hw *HTMLMessage) Focus() {
 | 
			
		||||
	hw.focused = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hw *HTMLMessage) Blur() {
 | 
			
		||||
	hw.focused = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hw *HTMLMessage) OnKeyEvent(event mauview.KeyEvent) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
@@ -154,7 +170,7 @@ func NewListEntity(ordered bool, start int, children []HTMLEntity) *ListEntity {
 | 
			
		||||
func (le *ListEntity) Draw(screen mauview.Screen) {
 | 
			
		||||
	width, _ := screen.Size()
 | 
			
		||||
 | 
			
		||||
	proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: le.Indent, Width: width - le.Indent}
 | 
			
		||||
	proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: le.Indent, Width: width - le.Indent, Style: le.Style}
 | 
			
		||||
	for i, entity := range le.Children {
 | 
			
		||||
		proxyScreen.Height = entity.Height()
 | 
			
		||||
		if le.Ordered {
 | 
			
		||||
@@ -165,6 +181,7 @@ func (le *ListEntity) Draw(screen mauview.Screen) {
 | 
			
		||||
			screen.SetContent(0, proxyScreen.OffsetY, '●', nil, le.Style)
 | 
			
		||||
		}
 | 
			
		||||
		entity.Draw(proxyScreen)
 | 
			
		||||
		proxyScreen.SetStyle(le.Style)
 | 
			
		||||
		proxyScreen.OffsetY += entity.Height()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -173,6 +190,31 @@ func (le *ListEntity) String() string {
 | 
			
		||||
	return fmt.Sprintf("&ListEntity{Ordered=%t, Start=%d, Base=%s},\n", le.Ordered, le.Start, le.BaseHTMLEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CodeBlockEntity struct {
 | 
			
		||||
	*BaseHTMLEntity
 | 
			
		||||
	Background tcell.Style
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewCodeBlockEntity(children []HTMLEntity, background tcell.Style) *CodeBlockEntity {
 | 
			
		||||
	return &CodeBlockEntity{
 | 
			
		||||
		BaseHTMLEntity: &BaseHTMLEntity{
 | 
			
		||||
			Tag:      "pre",
 | 
			
		||||
			Block:    true,
 | 
			
		||||
			Children: children,
 | 
			
		||||
		},
 | 
			
		||||
		Background: background,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ce *CodeBlockEntity) Draw(screen mauview.Screen) {
 | 
			
		||||
	screen.Fill(' ', ce.Background)
 | 
			
		||||
	ce.BaseHTMLEntity.Draw(screen)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ce *CodeBlockEntity) AdjustStyle(fn AdjustStyleFunc) HTMLEntity {
 | 
			
		||||
	return ce
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BreakEntity struct {
 | 
			
		||||
	*BaseHTMLEntity
 | 
			
		||||
}
 | 
			
		||||
@@ -297,13 +339,14 @@ func (he *BaseHTMLEntity) Draw(screen mauview.Screen) {
 | 
			
		||||
	}
 | 
			
		||||
	if len(he.Children) > 0 {
 | 
			
		||||
		prevBreak := false
 | 
			
		||||
		proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent}
 | 
			
		||||
		proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent, Style: he.Style}
 | 
			
		||||
		for i, entity := range he.Children {
 | 
			
		||||
			if i != 0 && entity.getStartX() == 0 {
 | 
			
		||||
				proxyScreen.OffsetY++
 | 
			
		||||
			}
 | 
			
		||||
			proxyScreen.Height = entity.Height()
 | 
			
		||||
			entity.Draw(proxyScreen)
 | 
			
		||||
			proxyScreen.SetStyle(he.Style)
 | 
			
		||||
			proxyScreen.OffsetY += entity.Height() - 1
 | 
			
		||||
			_, isBreak := entity.(*BreakEntity)
 | 
			
		||||
			if prevBreak && isBreak {
 | 
			
		||||
 
 | 
			
		||||
@@ -221,7 +221,7 @@ func styleEntryToStyle(se chroma.StyleEntry) tcell.Style {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEntity {
 | 
			
		||||
	lexer := lexers.Get(language)
 | 
			
		||||
	lexer := lexers.Get(strings.ToLower(language))
 | 
			
		||||
	if lexer == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -229,7 +229,9 @@ func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEn
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	// TODO allow changing theme
 | 
			
		||||
	style := styles.SolarizedDark
 | 
			
		||||
 | 
			
		||||
	tokens := iter.Tokens()
 | 
			
		||||
	children := make([]messages.HTMLEntity, len(tokens))
 | 
			
		||||
	for i, token := range tokens {
 | 
			
		||||
@@ -245,39 +247,26 @@ func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEn
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &messages.BaseHTMLEntity{
 | 
			
		||||
		Tag:      "pre",
 | 
			
		||||
		Block:    true,
 | 
			
		||||
		Children: children,
 | 
			
		||||
	}
 | 
			
		||||
	return messages.NewCodeBlockEntity(children, styleEntryToStyle(style.Get(chroma.Background)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (parser *htmlParser) codeblockToEntity(node *html.Node) messages.HTMLEntity {
 | 
			
		||||
	entity := &messages.BaseHTMLEntity{
 | 
			
		||||
		Tag:   "pre",
 | 
			
		||||
		Block: true,
 | 
			
		||||
	}
 | 
			
		||||
	lang := "plaintext"
 | 
			
		||||
	// TODO allow disabling syntax highlighting
 | 
			
		||||
	if node.FirstChild.Type == html.ElementNode && node.FirstChild.Data == "code" {
 | 
			
		||||
		text := (&messages.BaseHTMLEntity{
 | 
			
		||||
			Children: parser.nodeToEntities(node.FirstChild.FirstChild, false),
 | 
			
		||||
		}).PlainText()
 | 
			
		||||
		attr := parser.getAttribute(node.FirstChild, "class")
 | 
			
		||||
		var lang string
 | 
			
		||||
		node = node.FirstChild
 | 
			
		||||
		attr := parser.getAttribute(node, "class")
 | 
			
		||||
		for _, class := range strings.Split(attr, " ") {
 | 
			
		||||
			if strings.HasPrefix(class, "language-") {
 | 
			
		||||
				lang = class[len("language-"):]
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if len(lang) != 0 {
 | 
			
		||||
			if parsed := parser.syntaxHighlight(text, lang); parsed != nil {
 | 
			
		||||
				return parsed
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	entity.Children = parser.nodeToEntities(node.FirstChild, false)
 | 
			
		||||
	return entity
 | 
			
		||||
	text := (&messages.BaseHTMLEntity{
 | 
			
		||||
		Children: parser.nodeToEntities(node.FirstChild, false),
 | 
			
		||||
	}).PlainText()
 | 
			
		||||
	return parser.syntaxHighlight(text, lang)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (parser *htmlParser) tagNodeToEntity(node *html.Node, stripLinebreak bool) messages.HTMLEntity {
 | 
			
		||||
@@ -311,7 +300,7 @@ func (parser *htmlParser) singleNodeToEntity(node *html.Node, stripLinebreak boo
 | 
			
		||||
	switch node.Type {
 | 
			
		||||
	case html.TextNode:
 | 
			
		||||
		if stripLinebreak {
 | 
			
		||||
			node.Data = strings.Replace(node.Data, "\n", "", -1)
 | 
			
		||||
			node.Data = strings.ReplaceAll(node.Data, "\n", "")
 | 
			
		||||
		}
 | 
			
		||||
		return &messages.BaseHTMLEntity{
 | 
			
		||||
			Tag:  "text",
 | 
			
		||||
@@ -372,7 +361,7 @@ func ParseHTMLMessage(room *rooms.Room, evt *mautrix.Event, senderDisplayname st
 | 
			
		||||
			Tag: "emote",
 | 
			
		||||
			Children: []messages.HTMLEntity{
 | 
			
		||||
				messages.NewHTMLTextEntity("* "),
 | 
			
		||||
				messages.NewHTMLTextEntity("* ").AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(evt.Sender))),
 | 
			
		||||
				messages.NewHTMLTextEntity(senderDisplayname).AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(evt.Sender))),
 | 
			
		||||
				messages.NewHTMLTextEntity(" "),
 | 
			
		||||
				root,
 | 
			
		||||
			},
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user