方案: 使用iframe的方式 + 定义全局组件
定义组件
使用了一点点小技巧,iframe通讯动态更新iframe高度。
js
<script setup lang="ts">
import {onMounted, ref} from "vue";
const props = withDefaults(defineProps<{
width?: string,
src: string
}>(), {
width: '100%',
})
const heightRef = ref(`auto`)
const gistRef = ref<HTMLIFrameElement | null>(null)
onMounted(() => {
window.addEventListener('message', function (e) {
try {
if (typeof e.data === 'string' && e.data.includes(`${props.src}`)) {
const height = e.data.split('_').pop()
heightRef.value = `${+height + 2 /*iframe border*/}px`
}
} catch (error) {
console.log('(gist) iframe load error', error)
}
})
})
</script>
<template>
<iframe ref="gistRef"
class="rounded-xl border bg-card text-card-foreground shadow"
:width="width"
:height="heightRef"
:src="`data:text/html;charset=utf-8,
<head>
<base target='_blank' />
<style>
body {margin:0}
.gist .gist-file { margin-bottom: 0 !important;}
</style>
</head>
<body>
<script src='${props.src}'>
</script>
<script>
const heightX = document.body.scrollHeight
console.log('heightX', heightX)
window.parent.postMessage('__loadFinished_${props.src}_' + heightX, '*');
</script>
</body>`">
</iframe>
</template>
<script setup lang="ts">
import {onMounted, ref} from "vue";
const props = withDefaults(defineProps<{
width?: string,
src: string
}>(), {
width: '100%',
})
const heightRef = ref(`auto`)
const gistRef = ref<HTMLIFrameElement | null>(null)
onMounted(() => {
window.addEventListener('message', function (e) {
try {
if (typeof e.data === 'string' && e.data.includes(`${props.src}`)) {
const height = e.data.split('_').pop()
heightRef.value = `${+height + 2 /*iframe border*/}px`
}
} catch (error) {
console.log('(gist) iframe load error', error)
}
})
})
</script>
<template>
<iframe ref="gistRef"
class="rounded-xl border bg-card text-card-foreground shadow"
:width="width"
:height="heightRef"
:src="`data:text/html;charset=utf-8,
<head>
<base target='_blank' />
<style>
body {margin:0}
.gist .gist-file { margin-bottom: 0 !important;}
</style>
</head>
<body>
<script src='${props.src}'>
</script>
<script>
const heightX = document.body.scrollHeight
console.log('heightX', heightX)
window.parent.postMessage('__loadFinished_${props.src}_' + heightX, '*');
</script>
</body>`">
</iframe>
</template>
声明为全局组件
js
import Gist from './components/gist.vue';
export default {
...
enhanceApp({app, router, siteData}) {
app.component('gist', Gist)
}
}
import Gist from './components/gist.vue';
export default {
...
enhanceApp({app, router, siteData}) {
app.component('gist', Gist)
}
}
使用
markdown中使用:
md
<gist src="https://gist.github.com/tyrad/514c01c6580389f0fb2e377441ceec1c.js"/>
<gist src="https://gist.github.com/tyrad/514c01c6580389f0fb2e377441ceec1c.js"/>
效果预览: