aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2021-06-29 16:28:38 +0200
committerGitHub <noreply@github.com>2021-06-29 16:28:38 +0200
commit65548359cc5c78455b638c5be6fdec3e321e717a (patch)
tree0236a4aaa8e0c2a781e0383a39a667cf03528a1e
parentaac663e0da0af644ae1011d268d027160265dce3 (diff)
downloadgitea-65548359cc5c78455b638c5be6fdec3e321e717a.tar.gz
gitea-65548359cc5c78455b638c5be6fdec3e321e717a.zip
Add custom emoji support (#16004)
-rw-r--r--custom/conf/app.example.ini11
-rw-r--r--docs/content/doc/advanced/config-cheat-sheet.en-us.md3
-rw-r--r--modules/markup/html.go23
-rw-r--r--modules/markup/html_test.go13
-rw-r--r--modules/setting/setting.go10
-rw-r--r--modules/structs/settings.go1
-rw-r--r--modules/templates/helper.go3
-rw-r--r--routers/api/v1/settings/settings.go1
-rw-r--r--templates/base/head.tmpl1
-rw-r--r--templates/swagger/v1_json.tmpl7
-rw-r--r--web_src/js/features/emoji.js7
11 files changed, 57 insertions, 23 deletions
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 33ff7a62c5..7cae16cd79 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -1029,11 +1029,16 @@ PATH =
;; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`.
;THEMES = gitea,arc-green
;;
-;;All available reactions users can choose on issues/prs and comments.
-;;Values can be emoji alias (:smile:) or a unicode emoji.
-;;For custom reactions, add a tightly cropped square image to public/emoji/img/reaction_name.png
+;; All available reactions users can choose on issues/prs and comments.
+;; Values can be emoji alias (:smile:) or a unicode emoji.
+;; For custom reactions, add a tightly cropped square image to public/emoji/img/reaction_name.png
;REACTIONS = +1, -1, laugh, hooray, confused, heart, rocket, eyes
;;
+;; Additional Emojis not defined in the utf8 standard
+;; By default we support gitea (:gitea:), to add more copy them to public/emoji/img/emoji_name.png and add it to this config.
+;; Dont mistake it for Reactions.
+;CUSTOM_EMOJIS = gitea
+;;
;; Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
;DEFAULT_SHOW_FULL_NAME = false
;;
diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
index d1d47bc893..dc3b36cb4f 100644
--- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md
+++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
@@ -181,6 +181,9 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
Values can be emoji alias (:smile:) or a unicode emoji.
For custom reactions, add a tightly cropped square image to public/emoji/img/reaction_name.png
+- `CUSTOM_EMOJIS`: **gitea**: Additional Emojis not defined in the utf8 standard.
+ By default we support gitea (:gitea:), to add more copy them to public/emoji/img/emoji_name.png and
+ add it to this config.
- `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
- `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page.
- `USE_SERVICE_WORKER`: **true**: Whether to enable a Service Worker to cache frontend assets.
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 0cc0e23b5c..1e55629ab5 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -6,7 +6,6 @@ package markup
import (
"bytes"
- "fmt"
"io"
"io/ioutil"
"net/url"
@@ -66,7 +65,7 @@ var (
blackfridayExtRegex = regexp.MustCompile(`[^:]*:user-content-`)
// EmojiShortCodeRegex find emoji by alias like :smile:
- EmojiShortCodeRegex = regexp.MustCompile(`\:[\w\+\-]+\:{1}`)
+ EmojiShortCodeRegex = regexp.MustCompile(`:[\w\+\-]+:`)
)
// CSS class for action keywords (e.g. "closes: #1")
@@ -460,17 +459,14 @@ func createEmoji(content, class, name string) *html.Node {
return span
}
-func createCustomEmoji(alias, class string) *html.Node {
-
+func createCustomEmoji(alias string) *html.Node {
span := &html.Node{
Type: html.ElementNode,
Data: atom.Span.String(),
Attr: []html.Attribute{},
}
- if class != "" {
- span.Attr = append(span.Attr, html.Attribute{Key: "class", Val: class})
- span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: alias})
- }
+ span.Attr = append(span.Attr, html.Attribute{Key: "class", Val: "emoji"})
+ span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: alias})
img := &html.Node{
Type: html.ElementNode,
@@ -478,10 +474,8 @@ func createCustomEmoji(alias, class string) *html.Node {
Data: "img",
Attr: []html.Attribute{},
}
- if class != "" {
- img.Attr = append(img.Attr, html.Attribute{Key: "alt", Val: fmt.Sprintf(`:%s:`, alias)})
- img.Attr = append(img.Attr, html.Attribute{Key: "src", Val: fmt.Sprintf(`%s/assets/img/emoji/%s.png`, setting.StaticURLPrefix, alias)})
- }
+ img.Attr = append(img.Attr, html.Attribute{Key: "alt", Val: ":" + alias + ":"})
+ img.Attr = append(img.Attr, html.Attribute{Key: "src", Val: setting.StaticURLPrefix + "/assets/img/emoji/" + alias + ".png"})
span.AppendChild(img)
return span
@@ -948,9 +942,8 @@ func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) {
converted := emoji.FromAlias(alias)
if converted == nil {
// check if this is a custom reaction
- s := strings.Join(setting.UI.Reactions, " ") + "gitea"
- if strings.Contains(s, alias) {
- replaceContent(node, m[0], m[1], createCustomEmoji(alias, "emoji"))
+ if _, exist := setting.UI.CustomEmojisMap[alias]; exist {
+ replaceContent(node, m[0], m[1], createCustomEmoji(alias))
node = node.NextSibling.NextSibling
start = 0
continue
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 8c3d2b5395..85418892ef 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -284,7 +284,18 @@ func TestRender_emoji(t *testing.T) {
test(
":gitea:",
`<p><span class="emoji" aria-label="gitea"><img alt=":gitea:" src="`+setting.StaticURLPrefix+`/assets/img/emoji/gitea.png"/></span></p>`)
-
+ test(
+ ":custom-emoji:",
+ `<p>:custom-emoji:</p>`)
+ setting.UI.CustomEmojisMap["custom-emoji"] = ":custom-emoji:"
+ test(
+ ":custom-emoji:",
+ `<p><span class="emoji" aria-label="custom-emoji"><img alt=":custom-emoji:" src="`+setting.StaticURLPrefix+`/assets/img/emoji/custom-emoji.png"/></span></p>`)
+ test(
+ "θΏ™ζ˜―ε­—η¬¦:1::+1: some🐊 \U0001f44d:custom-emoji: :gitea:",
+ `<p>θΏ™ζ˜―ε­—η¬¦:1:<span class="emoji" aria-label="thumbs up">πŸ‘</span> some<span class="emoji" aria-label="crocodile">🐊</span> `+
+ `<span class="emoji" aria-label="thumbs up">πŸ‘</span><span class="emoji" aria-label="custom-emoji"><img alt=":custom-emoji:" src="`+setting.StaticURLPrefix+`/assets/img/emoji/custom-emoji.png"/></span> `+
+ `<span class="emoji" aria-label="gitea"><img alt=":gitea:" src="`+setting.StaticURLPrefix+`/assets/img/emoji/gitea.png"/></span></p>`)
test(
"Some text with πŸ˜„ in the middle",
`<p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">πŸ˜„</span> in the middle</p>`)
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index de167e288a..e37b788342 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -208,7 +208,9 @@ var (
DefaultTheme string
Themes []string
Reactions []string
- ReactionsMap map[string]bool
+ ReactionsMap map[string]bool `ini:"-"`
+ CustomEmojis []string
+ CustomEmojisMap map[string]string `ini:"-"`
SearchRepoDescription bool
UseServiceWorker bool
@@ -256,6 +258,8 @@ var (
DefaultTheme: `gitea`,
Themes: []string{`gitea`, `arc-green`},
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
+ CustomEmojis: []string{`gitea`},
+ CustomEmojisMap: map[string]string{"gitea": ":gitea:"},
Notification: struct {
MinTimeout time.Duration
TimeoutStep time.Duration
@@ -983,6 +987,10 @@ func NewContext() {
for _, reaction := range UI.Reactions {
UI.ReactionsMap[reaction] = true
}
+ UI.CustomEmojisMap = make(map[string]string)
+ for _, emoji := range UI.CustomEmojis {
+ UI.CustomEmojisMap[emoji] = ":" + emoji + ":"
+ }
}
func parseAuthorizedPrincipalsAllow(values []string) ([]string, bool) {
diff --git a/modules/structs/settings.go b/modules/structs/settings.go
index 842b12792d..90c4a2107b 100644
--- a/modules/structs/settings.go
+++ b/modules/structs/settings.go
@@ -18,6 +18,7 @@ type GeneralRepoSettings struct {
type GeneralUISettings struct {
DefaultTheme string `json:"default_theme"`
AllowedReactions []string `json:"allowed_reactions"`
+ CustomEmojis []string `json:"custom_emojis"`
}
// GeneralAPISettings contains global api settings exposed by it
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 83359a6ef2..f9b2dafd22 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -90,6 +90,9 @@ func NewFuncMap() []template.FuncMap {
"AllowedReactions": func() []string {
return setting.UI.Reactions
},
+ "CustomEmojis": func() map[string]string {
+ return setting.UI.CustomEmojisMap
+ },
"Safe": Safe,
"SafeJS": SafeJS,
"JSEscape": JSEscape,
diff --git a/routers/api/v1/settings/settings.go b/routers/api/v1/settings/settings.go
index e6417e4074..ca2d28fb8b 100644
--- a/routers/api/v1/settings/settings.go
+++ b/routers/api/v1/settings/settings.go
@@ -25,6 +25,7 @@ func GetGeneralUISettings(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, api.GeneralUISettings{
DefaultTheme: setting.UI.DefaultTheme,
AllowedReactions: setting.UI.Reactions,
+ CustomEmojis: setting.UI.CustomEmojis,
})
}
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index 10fc2bad4a..5091eda1e9 100644
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -30,6 +30,7 @@
AppVer: '{{AppVer}}',
AppSubUrl: '{{AppSubUrl}}',
AssetUrlPrefix: '{{AssetUrlPrefix}}',
+ CustomEmojis: {{CustomEmojis}},
UseServiceWorker: {{UseServiceWorker}},
csrf: '{{.CsrfToken}}',
HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}},
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 7f7907b3b0..40dddb06a0 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -14481,6 +14481,13 @@
},
"x-go-name": "AllowedReactions"
},
+ "custom_emojis": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "CustomEmojis"
+ },
"default_theme": {
"type": "string",
"x-go-name": "DefaultTheme"
diff --git a/web_src/js/features/emoji.js b/web_src/js/features/emoji.js
index 7a522b95fc..254a0b5c4d 100644
--- a/web_src/js/features/emoji.js
+++ b/web_src/js/features/emoji.js
@@ -1,8 +1,9 @@
import emojis from '../../../assets/emoji.json';
const {AssetUrlPrefix} = window.config;
+const {CustomEmojis} = window.config;
-const tempMap = {gitea: ':gitea:'};
+const tempMap = {...CustomEmojis};
for (const {emoji, aliases} of emojis) {
for (const alias of aliases || []) {
tempMap[alias] = emoji;
@@ -23,8 +24,8 @@ for (const key of emojiKeys) {
// retrieve HTML for given emoji name
export function emojiHTML(name) {
let inner;
- if (name === 'gitea') {
- inner = `<img alt=":${name}:" src="${AssetUrlPrefix}/img/emoji/gitea.png">`;
+ if (Object.prototype.hasOwnProperty.call(CustomEmojis, name)) {
+ inner = `<img alt=":${name}:" src="${AssetUrlPrefix}/img/emoji/${name}.png">`;
} else {
inner = emojiString(name);
}