diff options
author | 2023-12-27 11:23:52 +0100 | |
---|---|---|
committer | 2023-12-27 11:23:52 +0100 | |
commit | 0ff52b71f2c0e970b1f0d43793c019bbed93e112 (patch) | |
tree | eff120472b4b6f837121536ada03f530d213b13e /internal/text | |
parent | [bugfix] :innocent: (#2476) (diff) | |
download | gotosocial-0ff52b71f2c0e970b1f0d43793c019bbed93e112.tar.xz |
[chore] Refactor HTML templates and CSS (#2480)
* [chore] Refactor HTML templates and CSS
* eslint
* ignore "Local"
* rss tests
* fiddle with OG just a tiny bit
* dick around with polls a bit more so SR stops saying "clickable"
* remove break
* oh lord
* don't lazy load avatar
* fix ogmeta tests
* clean up some cruft
* catch remaining calls to c.HTML
* fix error rendering + stack overflow in tag
* allow templating attributes
* fix indent
* set aria-hidden on status complementary content, since it's already present in the label anyway
* tidy up templating calls a little
* try to make styling a bit more consistent + readable
* fix up some remaining CSS issues
* fix up reports
Diffstat (limited to 'internal/text')
-rw-r--r-- | internal/text/emojify.go | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/internal/text/emojify.go b/internal/text/emojify.go index 2100d5e81..23730eaf9 100644 --- a/internal/text/emojify.go +++ b/internal/text/emojify.go @@ -20,18 +20,76 @@ package text import ( "bytes" "html" + "html/template" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" "github.com/superseriousbusiness/gotosocial/internal/regexes" ) -// Emojify replaces shortcodes in `inputText` with the emoji in `emojis`. -// -// Callers should ensure that inputText and resulting text are escaped -// appropriately depending on what they're used for. -func Emojify(emojis []apimodel.Emoji, inputText string) string { - emojisMap := make(map[string]apimodel.Emoji, len(emojis)) +// EmojifyWeb replaces emoji shortcodes like `:example:` in the given HTML +// fragment with `<img>` tags suitable for rendering on the web frontend. +func EmojifyWeb(emojis []apimodel.Emoji, html template.HTML) template.HTML { + out := emojify( + emojis, + string(html), + func(url, code string, buf *bytes.Buffer) { + buf.WriteString(`<img src="`) + buf.WriteString(url) + buf.WriteString(`" title=":`) + buf.WriteString(code) + buf.WriteString(`:" alt=":`) + buf.WriteString(code) + buf.WriteString(`:" class="emoji" `) + // Lazy load emojis when + // they scroll into view. + buf.WriteString(`loading="lazy" `) + // Limit size to avoid showing + // huge emojis when unstyled. + buf.WriteString(`width="25" height="25"/>`) + }, + ) + + // If input was safe, + // we can trust output. + return template.HTML(out) // #nosec G203 +} +// EmojifyRSS replaces emoji shortcodes like `:example:` in the given text +// fragment with `<img>` tags suitable for rendering as RSS content. +func EmojifyRSS(emojis []apimodel.Emoji, text string) string { + return emojify( + emojis, + text, + func(url, code string, buf *bytes.Buffer) { + buf.WriteString(`<img src="`) + buf.WriteString(url) + buf.WriteString(`" title=":`) + buf.WriteString(code) + buf.WriteString(`:" alt=":`) + buf.WriteString(code) + buf.WriteString(`:" `) + // Limit size to avoid showing + // huge emojis in RSS readers. + buf.WriteString(`width="25" height="25"/>`) + }, + ) +} + +// Demojify replaces emoji shortcodes like `:example:` in the given text +// fragment with empty strings, essentially stripping them from the text. +// This is useful for text used in OG Meta headers. +func Demojify(text string) string { + return regexes.EmojiFinder.ReplaceAllString(text, "") +} + +func emojify( + emojis []apimodel.Emoji, + input string, + write func(url, code string, buf *bytes.Buffer), +) string { + // Build map of shortcodes. Normalize each + // shortcode by readding closing colons. + emojisMap := make(map[string]apimodel.Emoji, len(emojis)) for _, emoji := range emojis { shortcode := ":" + emoji.Shortcode + ":" emojisMap[shortcode] = emoji @@ -39,27 +97,20 @@ func Emojify(emojis []apimodel.Emoji, inputText string) string { return regexes.ReplaceAllStringFunc( regexes.EmojiFinder, - inputText, + input, func(shortcode string, buf *bytes.Buffer) string { - // Look for emoji according to this shortcode + // Look for emoji with 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"/>`) + // Escape raw emoji content. + url := html.EscapeString(emoji.URL) + code := html.EscapeString(emoji.Shortcode) + // Write emoji repr to buffer. + write(url, code, buf) return buf.String() }, ) |