From 4d21d27f94bc5c7c85712020991a679842e7c372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20S=C3=A1nchez?= Date: Tue, 27 Dec 2022 19:38:57 +0100 Subject: [PATCH] feat: render custom server emojis on editor (#579) --- components/content/ContentRich.setup.ts | 13 ++- .../publish/PublishEmojiPicker.client.vue | 7 +- components/publish/PublishWidget.vue | 5 +- composables/content-parse.ts | 10 +- composables/tiptap.ts | 8 ++ composables/tiptap/emoji.ts | 108 ++++++++++++++++++ tests/__snapshots__/html-parse.test.ts.snap | 2 +- 7 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 composables/tiptap/emoji.ts diff --git a/components/content/ContentRich.setup.ts b/components/content/ContentRich.setup.ts index 497e4add..d04aefed 100644 --- a/components/content/ContentRich.setup.ts +++ b/components/content/ContentRich.setup.ts @@ -1,5 +1,6 @@ import type { Emoji } from 'masto' import { emojisArrayToObject } from '~/composables/utils' +import { currentCustomEmojis } from '~/composables/emojis' defineOptions({ name: 'ContentRich', @@ -11,11 +12,21 @@ const { content, emojis, markdown = true } = defineProps<{ emojis?: Emoji[] }>() +const useEmojis = computed(() => { + const result: Emoji[] = [] + if (emojis) + result.push(...emojis) + + result.push(...currentCustomEmojis.value.emojis) + + return emojisArrayToObject(result) +}) + export default () => h( 'span', { class: 'content-rich' }, contentToVNode(content, { - emojis: emojisArrayToObject(emojis || []), + emojis: useEmojis.value, markdown, }), ) diff --git a/components/publish/PublishEmojiPicker.client.vue b/components/publish/PublishEmojiPicker.client.vue index fd2044d1..1e80c1ee 100644 --- a/components/publish/PublishEmojiPicker.client.vue +++ b/components/publish/PublishEmojiPicker.client.vue @@ -4,6 +4,7 @@ import { updateCustomEmojis } from '~/composables/emojis' const emit = defineEmits<{ (e: 'select', code: string): void + (e: 'selectCustom', image: any): void }>() const el = $ref() @@ -22,8 +23,10 @@ async function openEmojiPicker() { const { Picker } = await import('emoji-mart') picker = new Picker({ data: () => promise, - onEmojiSelect(e: any) { - emit('select', e.native || e.shortcodes) + onEmojiSelect({ native, src, alt, name }: any) { + native + ? emit('select', native) + : emit('selectCustom', { src, alt, 'data-emoji-id': name }) }, theme: isDark.value ? 'dark' : 'light', custom: customEmojisData.value, diff --git a/components/publish/PublishWidget.vue b/components/publish/PublishWidget.vue index 1460f535..635f9152 100644 --- a/components/publish/PublishWidget.vue +++ b/components/publish/PublishWidget.vue @@ -68,6 +68,9 @@ async function handlePaste(evt: ClipboardEvent) { function insertText(text: string) { editor.value?.chain().insertContent(text).focus().run() } +function insertEmoji(image: any) { + editor.value?.chain().focus().setEmoji(image).run() +} async function pickAttachments() { const files = await fileOpen([ @@ -277,7 +280,7 @@ defineExpose({ v-if="shouldExpanded" flex="~ gap-2 1" m="l--1" pt-2 justify="between" max-full border="t base" > - +