1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-20 09:26:23 -07:00

Add html truncating

This commit is contained in:
comraderat 2020-05-24 21:59:39 +02:00
parent 193913bcb4
commit 049207881a
3 changed files with 78 additions and 1 deletions

View file

@ -109,6 +109,7 @@ var funcMap = template.FuncMap{
}
return msg
},
"truncateHTMLMessage": truncateHTML,
"stripHTML": func(htmlStr template.HTML) string {
dom := x_html.NewTokenizer(strings.NewReader(string(htmlStr)))
for tokenType := dom.Next(); tokenType != x_html.ErrorToken; {

76
pkg/gctemplates/misc.go Normal file
View file

@ -0,0 +1,76 @@
package gctemplates
import (
"bytes"
"html/template"
"strings"
"github.com/gochan-org/gochan/pkg/gclog"
x_html "golang.org/x/net/html"
)
//TruncateHTML truncates a template.HTML string to a certain visible character limit and line limit
func truncateHTML(htmlText template.HTML, characterLimit int, maxLines int) template.HTML {
dom, err := x_html.Parse(strings.NewReader(string(htmlText)))
if err != nil {
gclog.Println(gclog.LErrorLog, err.Error())
return template.HTML("Server error truncating HTML, failed to parse html")
}
truncateHTMLNodes(dom, characterLimit, maxLines)
buf := new(bytes.Buffer)
x_html.Render(buf, dom)
return template.HTML(buf.String())
}
func removeNextSiblings(node *x_html.Node) {
if node == nil {
return
}
removeNextSiblings(node.NextSibling)
node.Parent.RemoveChild(node)
}
func truncateHTMLNodes(node *x_html.Node, charactersLeft int, linesLeft int) (charsLeft int, lineLeft int) {
//Uses a depth first search to map nodes and remove the rest.
if node == nil {
return charactersLeft, linesLeft
}
//if either value is 0 or less, remove next siblings and self
if charactersLeft <= 0 || linesLeft <= 0 {
removeNextSiblings(node)
}
switch node.Type {
case x_html.ElementNode:
//This is a tag node. If tag node is br, redude amount of lines by 1
if strings.ToLower(node.Data) == "br" {
linesLeft--
}
//Acts as normal node for the rest
fallthrough
case x_html.CommentNode:
fallthrough
case x_html.DoctypeNode:
fallthrough
case x_html.RawNode:
fallthrough
case x_html.ErrorNode:
fallthrough
case x_html.DocumentNode:
//None of the nodes directly contain text
//truncate children first
charactersLeft, linesLeft = truncateHTMLNodes(node.FirstChild, charactersLeft, linesLeft)
//Pass values to siblings (sibling code will immediately exit if no more chars allowed, and remove self)
return truncateHTMLNodes(node.NextSibling, charactersLeft, linesLeft)
case x_html.TextNode:
if len(node.Data) > charactersLeft {
node.Data = node.Data[0:charactersLeft-1] + "\n..."
}
charactersLeft -= len(node.Data)
return truncateHTMLNodes(node.NextSibling, charactersLeft, linesLeft)
}
gclog.Println(gclog.LErrorLog, "Did not match any known node type, possible error?: ", node)
return charactersLeft, linesLeft
}

View file

@ -22,7 +22,7 @@
{{end}}
{{end}}
<input type="checkbox" id="check{{$op.ID}}" name="check{{$op.ID}}" /><label class="post-info" for="check{{$op.ID}}"> <span class="subject">{{$op.Subject}}</span> <span class="postername">{{if ne $op.Email ""}}<a href="mailto:{{$op.Email}}">{{end}}{{if ne $op.Name ""}}{{$op.Name}}{{else}}{{if eq $op.Tripcode ""}}{{$.board.Anonymous}}{{end}}{{end}}{{if ne $op.Email ""}}</a>{{end}}</span>{{if ne $op.Tripcode ""}}<span class="tripcode">!{{$op.Tripcode}}</span>{{end}} {{formatTimestamp $op.Timestamp}} </label><a href="{{$.config.SiteWebfolder}}{{$.board.Dir}}/res/{{$op.ID}}.html#{{$op.ID}}">No.</a> <a href="javascript:quote({{$op.ID}})" class="backlink-click">{{$op.ID}}</a> <span class="post-links"> <span class="thread-ddown">[<a href="javascript:void(0)">&#9660;</a>]</span> <span>[<a href="{{$.config.SiteWebfolder}}{{$.board.Dir}}/res/{{$op.ID}}.html">View</a>]</span></span><br />
<div class="post-text">{{truncateMessage $op.MessageHTML 2222 18}}</div>
<div class="post-text">{{truncateHTMLMessage $op.MessageHTML 2222 18}}</div>
{{- if gt $thread.NumReplies 3}}
<b>{{subtract $thread.NumReplies 3}} post{{if gt $thread.NumReplies 4}}s{{end}} omitted</b>
{{end}}