Skip to content

10.vitepress文档如何引入gist

方案: 使用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"/>

效果预览: