72 lines
1.6 KiB
Vue
72 lines
1.6 KiB
Vue
<script setup lang="ts">
|
|
import { defineProps, onMounted, ref, watch } from "vue";
|
|
import DOMPurify from "dompurify";
|
|
|
|
const props = defineProps({
|
|
content: String,
|
|
type: String,
|
|
});
|
|
|
|
const iframe = ref<HTMLIFrameElement>();
|
|
|
|
// background vs color
|
|
const htmlDefault = (html: string) => {
|
|
return `
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Document</title>
|
|
</head>
|
|
<body style="margin: 0;">
|
|
${html}
|
|
</body>
|
|
</html>
|
|
`;
|
|
};
|
|
|
|
function setIframeContent(content: string | undefined) {
|
|
if (!iframe.value) return;
|
|
if (!content) return;
|
|
const doc = iframe.value.contentDocument || iframe.value.contentWindow?.document;
|
|
if (!doc) return;
|
|
// todo dompurify for image
|
|
const html = DOMPurify.sanitize(content, { FORBID_TAGS: ["style"] });
|
|
|
|
doc.open();
|
|
doc.write(htmlDefault(html));
|
|
doc.close();
|
|
}
|
|
|
|
watch(
|
|
() => props.content,
|
|
(content: string | undefined) => {
|
|
setIframeContent(content);
|
|
},
|
|
);
|
|
|
|
onMounted(() => {
|
|
setIframeContent(props.content);
|
|
});
|
|
</script>
|
|
<template>
|
|
<iframe :class="type" ref="iframe"></iframe>
|
|
</template>
|
|
|
|
<style scoped>
|
|
iframe {
|
|
overflow-y: auto;
|
|
max-height: 300px;
|
|
flex-basis: 100%;
|
|
border: none;
|
|
max-width: 640px; /* template width being 600px to 640px up to 750px (experiment and test) */
|
|
background-color: rgb(234, 234, 234);
|
|
}
|
|
|
|
.large {
|
|
max-height: 700px;
|
|
}
|
|
</style>
|