docling-studio/frontend/src/features/analysis/ui/MarkdownViewer.vue
2026-03-23 10:13:24 +01:00

93 lines
2 KiB
Vue

<template>
<!-- eslint-disable-next-line vue/no-v-html -- sanitized by DOMPurify -->
<div class="markdown-viewer" v-html="rendered" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { marked } from 'marked'
import DOMPurify from 'dompurify'
import { useI18n } from '../../../shared/i18n'
const props = defineProps({ content: String })
const { t } = useI18n()
const rendered = computed(() => {
if (!props.content) return `<p class="empty">${t('results.noMarkdown')}</p>`
return DOMPurify.sanitize(marked.parse(props.content) as string)
})
</script>
<style scoped>
.markdown-viewer {
font-size: 14px;
line-height: 1.8;
color: var(--text);
}
.markdown-viewer :deep(h1),
.markdown-viewer :deep(h2),
.markdown-viewer :deep(h3) {
color: var(--text);
margin: 24px 0 12px;
font-weight: 600;
}
.markdown-viewer :deep(h1) { font-size: 24px; }
.markdown-viewer :deep(h2) { font-size: 20px; }
.markdown-viewer :deep(h3) { font-size: 16px; }
.markdown-viewer :deep(p) { margin: 8px 0; }
.markdown-viewer :deep(code) {
background: var(--bg-elevated);
padding: 2px 6px;
border-radius: 4px;
font-family: 'IBM Plex Mono', monospace;
font-size: 13px;
}
.markdown-viewer :deep(pre) {
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 16px;
overflow-x: auto;
margin: 12px 0;
}
.markdown-viewer :deep(pre code) {
background: none;
padding: 0;
}
.markdown-viewer :deep(table) {
border-collapse: collapse;
width: 100%;
margin: 12px 0;
}
.markdown-viewer :deep(th),
.markdown-viewer :deep(td) {
border: 1px solid var(--border);
padding: 8px 12px;
text-align: left;
font-size: 13px;
}
.markdown-viewer :deep(th) {
background: var(--bg-elevated);
font-weight: 600;
}
.markdown-viewer :deep(img) {
max-width: 100%;
border-radius: var(--radius-sm);
}
.markdown-viewer :deep(.empty) {
color: var(--text-muted);
text-align: center;
padding: 40px;
}
</style>