diff --git a/components/account/AccountInfo.vue b/components/account/AccountInfo.vue index 703f42ce..9172c734 100644 --- a/components/account/AccountInfo.vue +++ b/components/account/AccountInfo.vue @@ -14,9 +14,7 @@ defineProps<{ -

- {{ account.displayName }} -

+

@{{ account.acct }}

diff --git a/components/account/AccountInlineInfo.vue b/components/account/AccountInlineInfo.vue index 8df90c90..b3777f9e 100644 --- a/components/account/AccountInlineInfo.vue +++ b/components/account/AccountInlineInfo.vue @@ -9,6 +9,6 @@ defineProps<{ diff --git a/components/common/RichContent.ts b/components/common/RichContent.ts index c8f2018c..a91b5fd0 100644 --- a/components/common/RichContent.ts +++ b/components/common/RichContent.ts @@ -1,3 +1,5 @@ +import type { Emoji } from 'masto' + export default defineComponent({ props: { content: { @@ -6,6 +8,15 @@ export default defineComponent({ }, }, setup(props) { - return () => contentToVNode(props.content) + const emojis = shallowRef>({}) + + onMounted(() => { + const { server } = useAppCookies() + const { serverInfos } = useClientState() + if (server.value) + emojis.value = serverInfos.value[server.value].customEmojis || {} + }) + + return () => h('div', { class: 'rich-content' }, contentToVNode(props.content, undefined, emojis.value)) }, }) diff --git a/components/status/StatusBody.vue b/components/status/StatusBody.vue index 687e8093..7e104f5f 100644 --- a/components/status/StatusBody.vue +++ b/components/status/StatusBody.vue @@ -11,23 +11,3 @@ const { status } = defineProps<{ - - diff --git a/composables/content.ts b/composables/content.ts index efe7d07b..57e62351 100644 --- a/composables/content.ts +++ b/composables/content.ts @@ -1,3 +1,4 @@ +import type { Emoji } from 'masto' import type { DefaultTreeAdapterMap } from 'parse5' import { parseFragment } from 'parse5' import type { VNode } from 'vue' @@ -33,7 +34,14 @@ export function defaultHandle(el: Element) { export function contentToVNode( content: string, handle: (node: Element) => Element | undefined | null | void = defaultHandle, + customEmojis: Record = {}, ): VNode { + content = content.replace(/:([\w-]+?):/g, (_, name) => { + const emoji = customEmojis[name] + if (emoji) + return `${name}` + return `:${name}:` + }) const tree = parseFragment(content) return h(Fragment, tree.childNodes.map(n => treeToVNode(n, handle))) } diff --git a/styles/global.css b/styles/global.css index 1340185f..7712fb9a 100644 --- a/styles/global.css +++ b/styles/global.css @@ -27,4 +27,29 @@ /* Force vertical scrollbar to be always visible to avoid layout shift while loading the content */ html { overflow-y: scroll; -} \ No newline at end of file +} + +.custom-emoji { + display: inline-block; + height: 1.2em; + width: 1.2em; + vertical-align: middle; +} + +.rich-content { + a { + --at-apply: text-primary hover:underline; + .invisible { + --at-apply: hidden; + } + .ellipsis { + --at-apply: truncate overflow-hidden ws-nowrap; + } + } + b { + --at-apply: font-bold; + } + p { + --at-apply: my-2; + } +}