-
Notifications
You must be signed in to change notification settings - Fork 154
/
Preview.vue
76 lines (65 loc) · 2 KB
/
Preview.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<script setup lang="ts">
import { onBeforeMount, ref, watch } from 'vue3'
import { onPreviewNavigated } from '../composables/content'
import { fetchPreviewOrigin, previewOrigin, previewUrl, previewPath } from '../composables/preview'
const iframe = ref<HTMLIFrameElement>()
const url = ref(previewUrl.value)
onBeforeMount(() => fetchPreviewOrigin())
watch(
[previewUrl, iframe],
() => {
url.value = previewUrl.value
updateIframe(previewUrl.value)
},
{ flush: 'post' }
)
function updateIframe(url: string) {
if (!iframe.value) return
if (!url.startsWith(previewOrigin.value) || previewPath.value.startsWith('/admin')) return updateIframeHard(url)
try {
// use nuxt router
iframe.value.contentWindow.$nuxt.$router.push(previewPath.value)
} catch (e) {
// fallback to hard refresh when working with cross-origin
updateIframeHard(url)
}
}
function updateIframeHard(url: string) {
if (iframe.value) iframe.value.src = url
}
function refresh() {
iframe.value.src += ''
}
function onUrlInput() {
if (url.value === previewUrl.value) return
updateIframe(url.value)
}
function onIframeLoad() {
try {
iframe.value.contentWindow.$nuxt.$router.afterEach(to => {
previewPath.value = to.path
onPreviewNavigated(to.path)
})
} catch (e) {
console.warn(e)
}
}
</script>
<template>
<div class="h-full flex-1 grid grid-rows-[min-content,1fr]">
<div class="p-2 flex d-border border-b gap-2">
<button class="px-1 opacity-50 hover:opacity-100" @click="refresh">
<heroicons-outline:refresh />
</button>
<input
v-model="url"
class="flex-auto my-auto px-2 bg-gray-400 bg-opacity-10 rounded px-2 py-1"
@keydown.enter="onUrlInput"
/>
<a :href="url" target="_blank" class="px-1 opacity-50 hover:opacity-100 block flex">
<heroicons-outline:external-link class="m-auto" />
</a>
</div>
<iframe ref="iframe" :src="previewOrigin" class="w-full h-full" @load="onIframeLoad" />
</div>
</template>