89 lines
2.1 KiB
Vue
89 lines
2.1 KiB
Vue
<template>
|
|
<slot
|
|
:data="data?.data"
|
|
:body="data?.body"
|
|
:toc="data?.toc"
|
|
:excerpt="data?.excerpt"
|
|
:error="error"
|
|
>
|
|
<MDCRenderer
|
|
v-if="body"
|
|
:tag="tag"
|
|
:class="props.class"
|
|
:body="body"
|
|
:data="data?.data"
|
|
:unwrap="props.unwrap"
|
|
:components="{
|
|
a: ProseA,
|
|
h1: ProseH1,
|
|
h2: ProseH2,
|
|
h3: ProseH3,
|
|
h4: ProseH4,
|
|
h5: ProseH5,
|
|
h6: ProseH6,
|
|
blockquote: ProseBlockquote,
|
|
}"
|
|
/>
|
|
</slot>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import ProseA from "~/components/content/prose/ProseA.vue";
|
|
import ProseH1 from "~/components/content/prose/ProseH1.vue";
|
|
import ProseH2 from "~/components/content/prose/ProseH2.vue";
|
|
import ProseH3 from "~/components/content/prose/ProseH3.vue";
|
|
import ProseH4 from "~/components/content/prose/ProseH4.vue";
|
|
import ProseH5 from "~/components/content/prose/ProseH5.vue";
|
|
import ProseH6 from "~/components/content/prose/ProseH6.vue";
|
|
import ProseBlockquote from "~/components/content/prose/ProseBlockquote.vue";
|
|
|
|
import { hash } from 'ohash'
|
|
import { useAsyncData } from 'nuxt/app'
|
|
import { watch, computed } from 'vue'
|
|
|
|
const props = defineProps({
|
|
tag: {
|
|
type: [String, Boolean],
|
|
default: 'div'
|
|
},
|
|
content: {
|
|
type: [String, Object],
|
|
required: true
|
|
},
|
|
excerpt: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
class: {
|
|
type: [String, Array, Object],
|
|
default: ''
|
|
},
|
|
unwrap: {
|
|
type: [Boolean, String],
|
|
default: false
|
|
}
|
|
})
|
|
const model = defineModel<number>({
|
|
default: 0,
|
|
});
|
|
|
|
const parser = useMarkdown();
|
|
const key = computed(() => hash(props.content))
|
|
|
|
const { data, refresh, error } = await useAsyncData(key.value, async () => {
|
|
const timer = performance.now();
|
|
if (typeof props.content !== 'string') {
|
|
model.value = performance.now() - timer;
|
|
return props.content
|
|
}
|
|
const result = await parser(props.content);
|
|
model.value = performance.now() - timer;
|
|
return result;
|
|
})
|
|
|
|
const body = computed(() => props.excerpt ? data.value?.excerpt : data.value?.body)
|
|
|
|
watch(() => props.content, () => {
|
|
refresh()
|
|
})
|
|
</script> |