shithub: hell

ref: 727a9f57ddf55c13114acaaa2bc872962cca9528
dir: /renderer.go/

View raw version
package main

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/k3a/html2text"

	mastodon "codeberg.org/penny64/hellclient-go-mastodon"
	"golang.org/x/net/html"
)

type StatusFormatter struct {
	hc          *Hellclient
	status      *mastodon.Status
	postContext *postref
}

// Returns the rendered content of a status
func (st *StatusFormatter) statusContent() string {
	renderedPost, plaintexts := st.hc.renderStatus(st.status.Content, st.postContext.ref)
	for key, plaintext := range plaintexts {
		renderedPost = strings.Replace(renderedPost, key, plaintext, 1)
	}
	renderedPost = html2text.HTML2Text(renderedPost)
	return renderedPost
}

func (st *StatusFormatter) username() string {
	var sb strings.Builder
	sb.WriteString("<")
	sb.WriteString(st.status.Account.Username)
	sb.WriteString(">")
	return sb.String()
}

func (hc *Hellclient) renderStatus(content string, index string) (string, map[string]string) {
	doc, err := html.Parse(strings.NewReader(content))
	if err != nil {
		fmt.Printf("Failed to parse status\n")
		return "", nil
	}

	//clear out the url map
	hc.urlMap[index] = []string{}
	preformats := make(map[string]string)

	for node := range doc.Descendants() {
		if (node.Data == "pre" || node.Data == "") && node.FirstChild != nil {
			preformats[fmt.Sprintf("%p%p", hc, node.FirstChild)] = node.FirstChild.Data
			node.FirstChild.Data = fmt.Sprintf("%p%p", hc, node.FirstChild)
		}
		if node.Data == "a" && node.Type == html.ElementNode {
			ismention := false
			href := ""

			for attr := range node.Attr {
				if node.Attr[attr].Key == "class" && strings.Contains(node.Attr[attr].Val, "mention") {
					node.Data = "div"
					ismention = true
					continue
				}
				if node.Attr[attr].Key == "href" {
					href = node.Attr[attr].Val
					//Replace the href with the description if the URL has one
					if node.FirstChild != nil && node.FirstChild.Type == html.TextNode && !ismention {
						node.Attr[attr].Val = fmt.Sprintf("(%s)", node.FirstChild.Data)
					} else {
						href = href + " "
					}
				}
			}
			if !ismention {
				hc.urlMap[index] = append(hc.urlMap[index], href)
				refnode := &html.Node{
					Type: html.TextNode,
					Data: fmt.Sprintf(" [%v]", len(hc.urlMap[index]))}
				if node.Parent != nil {
					node.Parent.InsertBefore(refnode, node.NextSibling)
				}
			}
		}
	}

	//Rip off the HTML body the parser made for us
	for node := range doc.Descendants() {
		if node.Data == "body" {
			node.Type = html.DocumentNode
			doc = node
		}
	}

	var rendered bytes.Buffer
	err = html.Render(&rendered, doc)

	if err != nil {
		return "", nil
	}

	renderedPlainText := rendered.String()

	return renderedPlainText, preformats
}