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 @@
-
{{ field.name }}
-
+
{{ field.name }}
+
\ 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 `
`;
+ });
+ }
+ },
+ });
+});
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,