package markup
import (
"bytes"
"html/template"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
// ChatLine renders one line of plain text, a title, with each ^N drawn
// the way chat draws it: the chat icon and the number, linked to the
// message. Nothing else in the line is read as markup, so a title is
// still the text its author wrote. A ^N means a message wherever it is
// written (dmestas, 2026-11-08); repo is the repository a bare ^N names.
func ChatLine(text, repo string) template.HTML { return chatLine(text, repo, true) }
// ChatLineIn is ChatLine for a title that is itself a link, a list
// row's: the message wears the same chip, as a span, because a link
// cannot hold another.
func ChatLineIn(text, repo string) template.HTML { return chatLine(text, repo, false) }
func chatLine(text, repo string, linked bool) template.HTML {
span := &html.Node{Type: html.ElementNode, Data: "span", DataAtom: atom.Span}
span.AppendChild(&html.Node{Type: html.TextNode, Data: text})
walkResolve(span, chatOnly{repo: repo})
if !linked {
for c := span.FirstChild; c != nil; c = c.NextSibling {
if c.Type == html.ElementNode && c.Data == "a" {
c.Data, c.DataAtom = "span", atom.Span
attrs := c.Attr[:0]
for _, a := range c.Attr {
if a.Key != "href" {
attrs = append(attrs, a)
}
}
c.Attr = attrs
}
}
}
var out bytes.Buffer
for c := span.FirstChild; c != nil; c = c.NextSibling {
if err := html.Render(&out, c); err != nil {
return template.HTML(template.HTMLEscapeString(text))
}
}
return template.HTML(out.String())
}
// chatOnly resolves message numbers and nothing else. A message needs
// no lookup: its permalink page is honest about one that is gone or
// unreadable, as chat's own links are.
type chatOnly struct{ repo string }
func (c chatOnly) ResolveToken(t RefToken) (string, bool) {
if t.Kind != RefChat {
return "", false
}
repo := t.Repo
if repo == "" {
repo = c.repo
}
if repo == "" {
return "", false
}
return "/r/" + repo + "/chat/" + t.ID, true
}
func (chatOnly) CaretIsChat() bool { return true }
func (chatOnly) SeqKind() string { return "" }
func (chatOnly) ResolveHash(string) string { return "" }
func (chatOnly) ResolveWiki(string) string { return "" }
func (chatOnly) ResolvePath(string) string { return "" }
func (chatOnly) ResolveAttachment(string, bool) string { return "" }
func (chatOnly) UserMark(string) string { return "" }