2022-08-03 12:47:00 +02:00
|
|
|
<script setup lang="ts">
|
|
|
|
import { Copy } from '@vicons/tabler';
|
2023-08-22 01:00:20 +02:00
|
|
|
import { useElementSize } from '@vueuse/core';
|
2022-08-03 12:47:00 +02:00
|
|
|
import hljs from 'highlight.js/lib/core';
|
|
|
|
import jsonHljs from 'highlight.js/lib/languages/json';
|
|
|
|
import sqlHljs from 'highlight.js/lib/languages/sql';
|
2022-08-17 14:36:52 +02:00
|
|
|
import xmlHljs from 'highlight.js/lib/languages/xml';
|
2023-03-27 17:31:13 +02:00
|
|
|
import yamlHljs from 'highlight.js/lib/languages/yaml';
|
2023-06-23 21:40:30 +02:00
|
|
|
import iniHljs from 'highlight.js/lib/languages/ini';
|
2023-08-22 01:00:20 +02:00
|
|
|
import { useCopy } from '@/composable/copy';
|
2022-08-03 12:47:00 +02:00
|
|
|
|
|
|
|
const props = withDefaults(
|
|
|
|
defineProps<{
|
2023-05-28 23:13:24 +02:00
|
|
|
value: string
|
|
|
|
followHeightOf?: HTMLElement | null
|
|
|
|
language?: string
|
|
|
|
copyPlacement?: 'top-right' | 'bottom-right' | 'outside' | 'none'
|
|
|
|
copyMessage?: string
|
2022-08-03 12:47:00 +02:00
|
|
|
}>(),
|
|
|
|
{
|
|
|
|
followHeightOf: null,
|
|
|
|
language: 'txt',
|
|
|
|
copyPlacement: 'top-right',
|
|
|
|
copyMessage: 'Copy to clipboard',
|
|
|
|
},
|
|
|
|
);
|
2023-05-28 23:13:24 +02:00
|
|
|
hljs.registerLanguage('sql', sqlHljs);
|
|
|
|
hljs.registerLanguage('json', jsonHljs);
|
|
|
|
hljs.registerLanguage('html', xmlHljs);
|
2023-06-18 12:27:26 +02:00
|
|
|
hljs.registerLanguage('xml', xmlHljs);
|
2023-05-28 23:13:24 +02:00
|
|
|
hljs.registerLanguage('yaml', yamlHljs);
|
2023-06-23 21:40:30 +02:00
|
|
|
hljs.registerLanguage('toml', iniHljs);
|
2023-05-28 23:13:24 +02:00
|
|
|
|
2022-08-03 12:47:00 +02:00
|
|
|
const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props);
|
2023-05-28 23:13:24 +02:00
|
|
|
const { height } = followHeightOf.value ? useElementSize(followHeightOf) : { height: ref(null) };
|
2022-08-03 12:47:00 +02:00
|
|
|
|
2023-08-22 01:00:20 +02:00
|
|
|
const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
|
|
|
|
const tooltipText = computed(() => isJustCopied.value ? 'Copied!' : copyMessage.value);
|
2022-08-03 12:47:00 +02:00
|
|
|
</script>
|
|
|
|
|
2023-05-28 23:13:24 +02:00
|
|
|
<template>
|
|
|
|
<div style="overflow-x: hidden; width: 100%">
|
|
|
|
<c-card class="result-card">
|
|
|
|
<n-scrollbar
|
|
|
|
x-scrollable
|
|
|
|
trigger="none"
|
|
|
|
:style="height ? `min-height: ${height - 40 /* card padding */ + 10 /* negative margin compensation */}px` : ''"
|
|
|
|
>
|
|
|
|
<n-config-provider :hljs="hljs">
|
|
|
|
<n-code :code="value" :language="language" :trim="false" data-test-id="area-content" />
|
|
|
|
</n-config-provider>
|
|
|
|
</n-scrollbar>
|
|
|
|
<n-tooltip v-if="value" trigger="hover">
|
|
|
|
<template #trigger>
|
|
|
|
<div class="copy-button" :class="[copyPlacement]">
|
2023-08-22 01:00:20 +02:00
|
|
|
<c-button circle important:h-10 important:w-10 @click="copy()">
|
2023-05-28 23:13:24 +02:00
|
|
|
<n-icon size="22" :component="Copy" />
|
|
|
|
</c-button>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<span>{{ tooltipText }}</span>
|
|
|
|
</n-tooltip>
|
|
|
|
</c-card>
|
|
|
|
<div v-if="copyPlacement === 'outside'" mt-4 flex justify-center>
|
2023-08-22 01:00:20 +02:00
|
|
|
<c-button @click="copy()">
|
2023-05-28 23:13:24 +02:00
|
|
|
{{ tooltipText }}
|
|
|
|
</c-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
2022-08-03 12:47:00 +02:00
|
|
|
<style lang="less" scoped>
|
|
|
|
::v-deep(.n-scrollbar) {
|
|
|
|
padding-bottom: 10px;
|
|
|
|
margin-bottom: -10px;
|
|
|
|
}
|
|
|
|
.result-card {
|
|
|
|
position: relative;
|
|
|
|
.copy-button {
|
|
|
|
position: absolute;
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
&.top-right {
|
|
|
|
top: 10px;
|
|
|
|
right: 10px;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.bottom-right {
|
|
|
|
bottom: 10px;
|
|
|
|
right: 10px;
|
|
|
|
}
|
|
|
|
&.outside,
|
|
|
|
&.none {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|