fix: resolve issues around rendering HTML response previews (#4890)

Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
Nivedin 2025-03-18 13:32:07 +05:30 committed by GitHub
parent 176e924bed
commit e2e5d4f1d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 14 deletions

View file

@ -98,6 +98,7 @@ import IconEyeOff from "~icons/lucide/eye-off"
import IconWrapText from "~icons/lucide/wrap-text"
import IconSave from "~icons/lucide/save"
import { HoppRESTRequestResponse } from "@hoppscotch/data"
import { computedAsync } from "@vueuse/core"
const t = useI18n()
const persistenceService = useService(PersistenceService)
@ -136,8 +137,12 @@ const { downloadIcon, downloadResponse } = useDownloadResponse(
request_name: responseName.value,
})
)
const defaultPreview =
(await persistenceService.getLocalConfig("lens_html_preview")) === "true"
const defaultPreview = computedAsync(
async () =>
(await persistenceService.getLocalConfig("lens_html_preview")) === "true",
false
)
const { previewFrame, previewEnabled, togglePreview } = usePreview(
defaultPreview,

View file

@ -1,7 +1,7 @@
import { HoppRESTResponse } from "@helpers/types/HoppRESTResponse"
import { copyToClipboard } from "@helpers/utils/clipboard"
import { refAutoReset } from "@vueuse/core"
import { computed, ComputedRef, onMounted, ref, Ref } from "vue"
import { computed, ComputedRef, ref, Ref, watch } from "vue"
import jsonToLanguage from "~/helpers/utils/json-to-language"
import { platform } from "~/platform"
@ -88,7 +88,7 @@ export function useDownloadResponse(
}
export function usePreview(
previewEnabledDefault: boolean,
previewEnabled: Ref<boolean>,
responseBodyText: Ref<string>
): {
previewFrame: Ref<HTMLIFrameElement | null>
@ -96,18 +96,8 @@ export function usePreview(
togglePreview: () => void
} {
const previewFrame: Ref<HTMLIFrameElement | null> = ref(null)
const previewEnabled = ref(previewEnabledDefault)
const url = ref("")
// `previewFrame` is a template ref that gets attached to the `iframe` element when the component mounts
// Ensures the HTML content is rendered immediately after a request, persists between tab switches, and is not limited to preview toggles
onMounted(() => updatePreviewFrame())
// Prevent updating the `iframe` element attributes during preview toggle actions after they are set initially
const shouldUpdatePreviewFrame = computed(
() => previewFrame.value?.getAttribute("data-previewing-url") !== url.value
)
const updatePreviewFrame = () => {
if (
previewEnabled.value &&
@ -126,9 +116,35 @@ export function usePreview(
// Finally, set the iframe source to the resulting HTML.
previewFrame.value.srcdoc = previewDocument.documentElement.outerHTML
previewFrame.value.setAttribute("data-previewing-url", url.value)
// Enable sandboxing for the iframe but this can have security implications
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox
// https://stackoverflow.com/a/30785417
// previewFrame.value.setAttribute(
// "sandbox",
// "allow-scripts allow-same-origin"
// )
}
}
// `previewFrame` is a template ref that gets attached to the `iframe` element when the component mounts
// Ensures the HTML content is rendered immediately after a request, persists between tab switches, and is not limited to preview toggles
// Also watches for changes in the `previewEnabled` state to update the `iframe` element attributes
watch(
previewEnabled,
() => {
updatePreviewFrame()
},
{
immediate: true,
}
)
// Prevent updating the `iframe` element attributes during preview toggle actions after they are set initially
const shouldUpdatePreviewFrame = computed(
() => previewFrame.value?.getAttribute("data-previewing-url") !== url.value
)
const togglePreview = () => {
previewEnabled.value = !previewEnabled.value
updatePreviewFrame()