HTMLLensRenderer.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <div>
  3. <div
  4. class="
  5. bg-primary
  6. border-b border-dividerLight
  7. flex flex-1
  8. top-lowerSecondaryStickyFold
  9. pl-4
  10. z-10
  11. sticky
  12. items-center
  13. justify-between
  14. "
  15. >
  16. <label class="font-semibold text-secondaryLight">
  17. {{ $t("response.body") }}
  18. </label>
  19. <div class="flex">
  20. <ButtonSecondary
  21. v-if="response.body"
  22. v-tippy="{ theme: 'tooltip' }"
  23. :title="
  24. previewEnabled ? $t('hide.preview') : $t('response.preview_html')
  25. "
  26. :svg="!previewEnabled ? 'eye' : 'eye-off'"
  27. @click.native.prevent="togglePreview"
  28. />
  29. <ButtonSecondary
  30. v-if="response.body"
  31. ref="downloadResponse"
  32. v-tippy="{ theme: 'tooltip' }"
  33. :title="$t('action.download_file')"
  34. :svg="downloadIcon"
  35. @click.native="downloadResponse"
  36. />
  37. <ButtonSecondary
  38. v-if="response.body"
  39. ref="copyResponse"
  40. v-tippy="{ theme: 'tooltip' }"
  41. :title="$t('action.copy')"
  42. :svg="copyIcon"
  43. @click.native="copyResponse"
  44. />
  45. </div>
  46. </div>
  47. <div class="relative">
  48. <SmartAceEditor
  49. :value="responseBodyText"
  50. :lang="'html'"
  51. :options="{
  52. maxLines: Infinity,
  53. minLines: 16,
  54. autoScrollEditorIntoView: true,
  55. readOnly: true,
  56. showPrintMargin: false,
  57. useWorker: false,
  58. }"
  59. styles="border-b border-dividerLight"
  60. />
  61. <iframe
  62. ref="previewFrame"
  63. :class="{ hidden: !previewEnabled }"
  64. class="covers-response"
  65. src="about:blank"
  66. ></iframe>
  67. </div>
  68. </div>
  69. </template>
  70. <script>
  71. import { defineComponent } from "@nuxtjs/composition-api"
  72. import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
  73. import { copyToClipboard } from "~/helpers/utils/clipboard"
  74. export default defineComponent({
  75. mixins: [TextContentRendererMixin],
  76. props: {
  77. response: { type: Object, default: () => {} },
  78. },
  79. data() {
  80. return {
  81. downloadIcon: "download",
  82. copyIcon: "copy",
  83. previewEnabled: false,
  84. }
  85. },
  86. methods: {
  87. downloadResponse() {
  88. const dataToWrite = this.responseBodyText
  89. const file = new Blob([dataToWrite], { type: "text/html" })
  90. const a = document.createElement("a")
  91. const url = URL.createObjectURL(file)
  92. a.href = url
  93. // TODO get uri from meta
  94. a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
  95. document.body.appendChild(a)
  96. a.click()
  97. this.downloadIcon = "check"
  98. this.$toast.success(this.$t("state.download_started"), {
  99. icon: "downloading",
  100. })
  101. setTimeout(() => {
  102. document.body.removeChild(a)
  103. URL.revokeObjectURL(url)
  104. this.downloadIcon = "download"
  105. }, 1000)
  106. },
  107. copyResponse() {
  108. copyToClipboard(this.responseBodyText)
  109. this.copyIcon = "check"
  110. this.$toast.success(this.$t("state.copied_to_clipboard"), {
  111. icon: "content_paste",
  112. })
  113. setTimeout(() => (this.copyIcon = "copy"), 1000)
  114. },
  115. togglePreview() {
  116. this.previewEnabled = !this.previewEnabled
  117. if (this.previewEnabled) {
  118. if (
  119. this.$refs.previewFrame.getAttribute("data-previewing-url") ===
  120. this.url
  121. )
  122. return
  123. // Use DOMParser to parse document HTML.
  124. const previewDocument = new DOMParser().parseFromString(
  125. this.responseBodyText,
  126. "text/html"
  127. )
  128. // Inject <base href="..."> tag to head, to fix relative CSS/HTML paths.
  129. previewDocument.head.innerHTML =
  130. `<base href="${this.url}">` + previewDocument.head.innerHTML
  131. // Finally, set the iframe source to the resulting HTML.
  132. this.$refs.previewFrame.srcdoc =
  133. previewDocument.documentElement.outerHTML
  134. this.$refs.previewFrame.setAttribute("data-previewing-url", this.url)
  135. }
  136. },
  137. },
  138. })
  139. </script>
  140. <style lang="scss" scoped>
  141. .covers-response {
  142. @apply absolute;
  143. @apply inset-0;
  144. @apply bg-white;
  145. @apply h-full;
  146. @apply w-full;
  147. @apply border;
  148. @apply border-dividerLight;
  149. }
  150. </style>