From 348b1ba2b006097d4944537fff91b62cc9a8d6fc Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Mon, 2 Dec 2024 22:21:04 +0100 Subject: [PATCH] feat: :sparkles: Implement custom emojis --- components/notes/content.vue | 5 ++- components/notes/header.vue | 5 ++- components/notes/note.vue | 6 +-- components/notes/reblog-header.vue | 4 +- components/notifications/follow-request.vue | 2 +- components/notifications/notification.vue | 2 +- components/profiles/profile-content.vue | 5 ++- components/profiles/profile-fields.vue | 7 +-- components/profiles/profile.vue | 6 +-- components/sidebars/sidebar.vue | 4 +- plugins/EmojiRenderer.ts | 49 +++++++++++++++++++++ settings.ts | 2 +- 12 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 plugins/EmojiRenderer.ts diff --git a/components/notes/content.vue b/components/notes/content.vue index 7a28299..d266a63 100644 --- a/components/notes/content.vue +++ b/components/notes/content.vue @@ -3,7 +3,7 @@ maxHeight: collapsed ? '18rem' : `${container?.scrollHeight}px` }">
+ v-html="content" v-render-emojis="emojis">
@@ -24,7 +24,7 @@ diff --git a/components/profiles/profile-fields.vue b/components/profiles/profile-fields.vue index c41b1c5..6243f96 100644 --- a/components/profiles/profile-fields.vue +++ b/components/profiles/profile-fields.vue @@ -1,16 +1,17 @@ \ No newline at end of file diff --git a/components/profiles/profile.vue b/components/profiles/profile.vue index 24bfdfb..53b5857 100644 --- a/components/profiles/profile.vue +++ b/components/profiles/profile.vue @@ -17,7 +17,7 @@
- + {{ account.display_name }} @@ -36,13 +36,13 @@
- + - + diff --git a/components/sidebars/sidebar.vue b/components/sidebars/sidebar.vue index 92e02ab..c84acc0 100644 --- a/components/sidebars/sidebar.vue +++ b/components/sidebars/sidebar.vue @@ -199,7 +199,7 @@ const instance = useInstance(); AA
- {{ + {{ identity?.account.display_name }} @{{ identity?.account.acct }} @@ -216,7 +216,7 @@ const instance = useInstance(); AA
- {{ + {{ identity?.account.display_name }} @{{ diff --git a/plugins/EmojiRenderer.ts b/plugins/EmojiRenderer.ts new file mode 100644 index 0000000..83a8ace --- /dev/null +++ b/plugins/EmojiRenderer.ts @@ -0,0 +1,49 @@ +import type { Emoji } from "@versia/client/types"; +import { SettingIds } from "~/settings"; + +const emojisRegex = + /\p{RI}\p{RI}|\p{Emoji}(\p{EMod}|\uFE0F\u20E3?|[\u{E0020}-\u{E007E}]+\u{E007F})?(\u200D(\p{RI}\p{RI}|\p{Emoji}(\p{EMod}|\uFE0F\u20E3?|[\u{E0020}-\u{E007E}]+\u{E007F})?))*/gu; +const incorrectEmojisRegex = /^[#*0-9©®]$/; + +export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.vueApp.directive("render-emojis", { + beforeMount(el, binding) { + const shouldRenderEmoji = useSetting(SettingIds.CustomEmojis); + const emojiFont = useSetting(SettingIds.EmojiTheme); + + // Replace emoji shortcodes with images + if (shouldRenderEmoji.value.value) { + el.innerHTML = el.innerHTML.replace( + /:([a-zA-Z0-9_-]+):/g, + (match, emoji) => { + const emojiData = binding.value.find( + (e) => e.shortcode === emoji, + ); + + if (!emojiData) { + return match; + } + + const image = document.createElement("img"); + image.src = emojiData.url; + image.alt = `:${emoji}:`; + image.title = emojiData.shortcode; + image.className = + "h-[1lh] align-middle inline not-prose hover:scale-110 transition-transform duration-75 ease-in-out"; + return image.outerHTML; + }, + ); + } + + if (emojiFont.value.value !== "native") { + el.innerHTML = el.innerHTML.replace(emojisRegex, (match) => { + if (incorrectEmojisRegex.test(match)) { + return match; + } + + return `${match}`; + }); + } + }, + }); +}); diff --git a/settings.ts b/settings.ts index 61c144e..f89f9f2 100644 --- a/settings.ts +++ b/settings.ts @@ -123,7 +123,7 @@ export const settings: Record = { } as EnumSetting, [SettingIds.CustomEmojis]: { title: "Render Custom Emojis", - description: "Render custom emojis.", + description: "Render custom emojis. Requires a page reload to apply.", type: SettingType.Boolean, value: true, page: SettingPages.Behaviour,