summaryrefslogtreecommitdiff
path: root/internal/router/template.go
diff options
context:
space:
mode:
authorLibravatar Blackle Morisanchetto <isabelle@blackle-mori.com>2022-09-02 05:54:32 -0400
committerLibravatar GitHub <noreply@github.com>2022-09-02 11:54:32 +0200
commit1e1cdee06a3bd5aaa0f97ad3c0d25aa505e723ef (patch)
tree85be3b04d0737980082c5f78c52b51759aa0bb5b /internal/router/template.go
parent[bugfix] Fix occasional federatingdb test fail (#792) (diff)
downloadgotosocial-1e1cdee06a3bd5aaa0f97ad3c0d25aa505e723ef.tar.xz
[feature] Emojify spoiler and content in web templates (#785)
* Emojify spoiler and content in web templates * Use more performance emojify code (thanks NyaaaWhatsUpDoc!)
Diffstat (limited to 'internal/router/template.go')
-rw-r--r--internal/router/template.go52
1 files changed, 52 insertions, 0 deletions
diff --git a/internal/router/template.go b/internal/router/template.go
index ebd8629e8..a9d5726ea 100644
--- a/internal/router/template.go
+++ b/internal/router/template.go
@@ -19,7 +19,9 @@
package router
import (
+ "bytes"
"fmt"
+ "html"
"html/template"
"os"
"path/filepath"
@@ -28,6 +30,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
+ "github.com/superseriousbusiness/gotosocial/internal/regexes"
)
// LoadTemplates loads html templates for use by the given engine
@@ -57,6 +60,11 @@ func oddOrEven(n int) string {
return "odd"
}
+func escape(str string) template.HTML {
+ /* #nosec G203 */
+ return template.HTML(template.HTMLEscapeString(str))
+}
+
func noescape(str string) template.HTML {
/* #nosec G203 */
return template.HTML(str)
@@ -97,12 +105,56 @@ func visibilityIcon(visibility model.Visibility) template.HTML {
return template.HTML(fmt.Sprintf(`<i aria-label="Visibility: %v" class="fa fa-%v"></i>`, icon.label, icon.faIcon))
}
+// replaces shortcodes in `text` with the emoji in `emojis`
+// text is a template.HTML to affirm that the input of this function is already escaped
+func emojify(emojis []model.Emoji, text template.HTML) template.HTML {
+ emojisMap := make(map[string]model.Emoji, len(emojis))
+
+ for _, emoji := range emojis {
+ shortcode := ":" + emoji.Shortcode + ":"
+ emojisMap[shortcode] = emoji
+ }
+
+ out := regexes.ReplaceAllStringFunc(
+ regexes.EmojiFinder,
+ string(text),
+ func(shortcode string, buf *bytes.Buffer) string {
+ // Look for emoji according to this shortcode
+ emoji, ok := emojisMap[shortcode]
+ if !ok {
+ return shortcode
+ }
+
+ // Escape raw emoji content
+ safeURL := html.EscapeString(emoji.URL)
+ safeCode := html.EscapeString(emoji.Shortcode)
+
+ // Write HTML emoji repr to buffer
+ buf.WriteString(`<img src="`)
+ buf.WriteString(safeURL)
+ buf.WriteString(`" title=":`)
+ buf.WriteString(safeCode)
+ buf.WriteString(`:" alt=":`)
+ buf.WriteString(safeCode)
+ buf.WriteString(`:" class="emoji"/>`)
+
+ return buf.String()
+ },
+ )
+
+ /* #nosec G203 */
+ // (this is escaped above)
+ return template.HTML(out)
+}
+
func LoadTemplateFunctions(engine *gin.Engine) {
engine.SetFuncMap(template.FuncMap{
+ "escape": escape,
"noescape": noescape,
"oddOrEven": oddOrEven,
"visibilityIcon": visibilityIcon,
"timestamp": timestamp,
"timestampShort": timestampShort,
+ "emojify": emojify,
})
}