158 lines
3.5 KiB
Vue
158 lines
3.5 KiB
Vue
<script setup lang="ts">
|
|
import { configuredXss, renderHighlightedString } from '@modrinth/utils'
|
|
import { computed } from 'vue'
|
|
|
|
import {
|
|
prepareDescription,
|
|
renderTranslatedDescription,
|
|
type TranslationMode,
|
|
type TranslationStyle,
|
|
} from '@/helpers/translation'
|
|
|
|
const props = defineProps<{
|
|
description: string
|
|
active: boolean
|
|
translations: Record<string, string>
|
|
mode: TranslationMode
|
|
style: TranslationStyle
|
|
format?: 'markdown' | 'html'
|
|
}>()
|
|
|
|
const renderedDescription = computed(() => {
|
|
if (!props.active) {
|
|
return props.format === 'html'
|
|
? configuredXss.process(props.description ?? '')
|
|
: renderHighlightedString(props.description ?? '')
|
|
}
|
|
return renderTranslatedDescription(
|
|
prepareDescription(props.description, props.format),
|
|
props.translations,
|
|
props.mode,
|
|
props.style,
|
|
)
|
|
})
|
|
|
|
const translationOnlyClass = computed(() =>
|
|
props.active && props.mode === 'translation-only'
|
|
? ['ax-translation-only', `ax-translation-style-${props.style}`]
|
|
: [],
|
|
)
|
|
</script>
|
|
|
|
<template>
|
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
<div class="markdown-body" :class="translationOnlyClass" v-html="renderedDescription" />
|
|
</template>
|
|
|
|
<style scoped>
|
|
:deep(.ax-translation-block) {
|
|
margin-block: 0.5rem 1rem;
|
|
animation: translation-float-in 0.5s ease-out both;
|
|
}
|
|
|
|
:deep(.ax-translation-block > :first-child) {
|
|
margin-top: 0;
|
|
}
|
|
|
|
:deep(.ax-translation-block > :last-child) {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
:deep(.ax-translation-style-weakened) {
|
|
color: var(--color-secondary) !important;
|
|
}
|
|
|
|
:deep(.ax-translation-style-blur) {
|
|
filter: blur(4px);
|
|
opacity: 0.75;
|
|
transition:
|
|
filter 0.1s ease-in-out,
|
|
opacity 0.1s ease-in-out;
|
|
}
|
|
|
|
:deep(.ax-translation-style-blur:hover) {
|
|
filter: blur(0);
|
|
opacity: 1;
|
|
}
|
|
|
|
:deep(.ax-translation-style-blockquote) {
|
|
padding: 4px 0 4px 8px;
|
|
border-left: 4px solid var(--color-brand);
|
|
}
|
|
|
|
:deep(.ax-translation-style-dashed-line) {
|
|
text-decoration: underline dashed var(--color-brand) !important;
|
|
text-underline-offset: 5px;
|
|
}
|
|
|
|
:deep(.ax-translation-style-border) {
|
|
padding: 2px 4px;
|
|
border: 1px solid var(--color-brand);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
:deep(.ax-translation-style-text-color) {
|
|
color: oklch(0.693 0.17 162.48) !important;
|
|
}
|
|
|
|
:deep(.ax-translation-style-background) {
|
|
padding: 2px 4px;
|
|
border-radius: 4px;
|
|
background-color: color-mix(in srgb, var(--color-brand) 15%, transparent);
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-weakened {
|
|
color: var(--color-secondary) !important;
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-blur {
|
|
filter: blur(4px);
|
|
opacity: 0.75;
|
|
transition:
|
|
filter 0.1s ease-in-out,
|
|
opacity 0.1s ease-in-out;
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-blur:hover {
|
|
filter: blur(0);
|
|
opacity: 1;
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-blockquote {
|
|
padding: 4px 0 4px 8px;
|
|
border-left: 4px solid var(--color-brand);
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-dashed-line {
|
|
text-decoration: underline dashed var(--color-brand) !important;
|
|
text-underline-offset: 5px;
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-border {
|
|
padding: 2px 4px;
|
|
border: 1px solid var(--color-brand);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-text-color {
|
|
color: oklch(0.693 0.17 162.48) !important;
|
|
}
|
|
|
|
.ax-translation-only.ax-translation-style-background {
|
|
padding: 2px 4px;
|
|
border-radius: 4px;
|
|
background-color: color-mix(in srgb, var(--color-brand) 15%, transparent);
|
|
}
|
|
|
|
@keyframes translation-float-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(12px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
</style>
|