u
This commit is contained in:
commit
c570ec514c
550 files changed
+152597
No files matched your search
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div ref="sandboxRef" class="email-renderer"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, nextTick } from "vue";
|
||||
import { useRouterStore } from "@/store/modules/router";
|
||||
|
||||
const routerStore = useRouterStore();
|
||||
|
||||
const props = defineProps<{
|
||||
html: string;
|
||||
}>();
|
||||
|
||||
const sandboxRef = ref<HTMLDivElement | null>(null);
|
||||
let shadowRoot: ShadowRoot | null = null;
|
||||
|
||||
function sanitizeHtml(html: string): string {
|
||||
// 简单去除 <script> 标签及其内容
|
||||
return html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "");
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.html,
|
||||
async (newHtml) => {
|
||||
if (!sandboxRef.value) return;
|
||||
|
||||
await nextTick();
|
||||
|
||||
if (!shadowRoot) {
|
||||
shadowRoot = sandboxRef.value.attachShadow({ mode: "open" });
|
||||
|
||||
// 监听shadowRoot里的点击事件,事件委托拦截a标签
|
||||
shadowRoot.addEventListener("click", (e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const anchor = target.closest("a");
|
||||
if (anchor && anchor.getAttribute("href")?.startsWith("mailto:")) {
|
||||
e.preventDefault();
|
||||
const email = anchor.getAttribute("href")!.replace("mailto:", "");
|
||||
if (email) {
|
||||
routerStore.navigateTo({
|
||||
path: "/write",
|
||||
query: {
|
||||
toEmail: email
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 先清空
|
||||
shadowRoot.innerHTML = "";
|
||||
|
||||
// 安全过滤
|
||||
const safeHtml = sanitizeHtml(newHtml);
|
||||
|
||||
// 直接插入,保留里面的 <style> 标签
|
||||
shadowRoot.innerHTML = `
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
table {
|
||||
max-width: 100%;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.wrapper {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
<div class="wrapper">
|
||||
${safeHtml}
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.email-renderer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user