@scalar/api-client 3.19.3 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/components/HttpMethod/HttpMethod.vue.d.ts +2 -2
  3. package/dist/components/SectionFilter.vue.d.ts +2 -0
  4. package/dist/components/SectionFilter.vue.d.ts.map +1 -1
  5. package/dist/components/SectionFilter.vue.js +1 -1
  6. package/dist/components/SectionFilter.vue.js.map +1 -1
  7. package/dist/components/SectionFilter.vue.script.js +11 -8
  8. package/dist/components/SectionFilter.vue.script.js.map +1 -1
  9. package/dist/components/Server/ServerVariablesSelect.vue.d.ts.map +1 -1
  10. package/dist/components/Server/ServerVariablesSelect.vue.js.map +1 -1
  11. package/dist/components/Server/ServerVariablesSelect.vue.script.js +5 -3
  12. package/dist/components/Server/ServerVariablesSelect.vue.script.js.map +1 -1
  13. package/dist/components/Server/ServerVariablesTextbox.vue.d.ts.map +1 -1
  14. package/dist/components/Server/ServerVariablesTextbox.vue.js.map +1 -1
  15. package/dist/components/Server/ServerVariablesTextbox.vue.script.js +6 -3
  16. package/dist/components/Server/ServerVariablesTextbox.vue.script.js.map +1 -1
  17. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.d.ts.map +1 -1
  18. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.js.map +1 -1
  19. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js +4 -2
  20. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js.map +1 -1
  21. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.d.ts.map +1 -1
  22. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.js.map +1 -1
  23. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js +3 -1
  24. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js.map +1 -1
  25. package/dist/style.css +159 -135
  26. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +2 -0
  27. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  28. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  29. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +9 -3
  30. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  31. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
  32. package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
  33. package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
  34. package/dist/v2/blocks/operation-block/components/Header.vue.script.js +10 -6
  35. package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
  36. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.d.ts.map +1 -1
  37. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.js +1 -1
  38. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.js.map +1 -1
  39. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js +4 -2
  40. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js.map +1 -1
  41. package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
  42. package/dist/v2/blocks/operation-block/helpers/send-request.js +4 -3
  43. package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
  44. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +2 -0
  45. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
  46. package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
  47. package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
  48. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +51 -26
  49. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
  50. package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
  51. package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
  52. package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
  53. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +28 -8
  54. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
  55. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.d.ts.map +1 -1
  56. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.js.map +1 -1
  57. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js +9 -3
  58. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js.map +1 -1
  59. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.d.ts.map +1 -1
  60. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.js.map +1 -1
  61. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.script.js +6 -4
  62. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.script.js.map +1 -1
  63. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
  64. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
  65. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +3 -1
  66. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
  67. package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts.map +1 -1
  68. package/dist/v2/blocks/request-block/components/RequestParams.vue.js.map +1 -1
  69. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js +7 -5
  70. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js.map +1 -1
  71. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +2 -2
  72. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
  73. package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
  74. package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
  75. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +40 -7
  76. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
  77. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +12 -12
  78. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
  79. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
  80. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +24 -20
  81. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
  82. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.d.ts.map +1 -1
  83. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.js.map +1 -1
  84. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js +6 -4
  85. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js.map +1 -1
  86. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.d.ts.map +1 -1
  87. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +5 -4
  88. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
  89. package/dist/v2/blocks/response-block/ResponseBlock.vue.d.ts.map +1 -1
  90. package/dist/v2/blocks/response-block/ResponseBlock.vue.js +1 -1
  91. package/dist/v2/blocks/response-block/ResponseBlock.vue.js.map +1 -1
  92. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js +34 -13
  93. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js.map +1 -1
  94. package/dist/v2/blocks/response-block/components/Headers.vue.d.ts +3 -3
  95. package/dist/v2/blocks/response-block/components/Headers.vue.d.ts.map +1 -1
  96. package/dist/v2/blocks/response-block/components/Headers.vue.js.map +1 -1
  97. package/dist/v2/blocks/response-block/components/Headers.vue.script.js +5 -3
  98. package/dist/v2/blocks/response-block/components/Headers.vue.script.js.map +1 -1
  99. package/dist/v2/blocks/response-block/components/ResponseBody.vue.d.ts.map +1 -1
  100. package/dist/v2/blocks/response-block/components/ResponseBody.vue.js +1 -1
  101. package/dist/v2/blocks/response-block/components/ResponseBody.vue.js.map +1 -1
  102. package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js +3 -1
  103. package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js.map +1 -1
  104. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.d.ts.map +1 -1
  105. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.js.map +1 -1
  106. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js +11 -3
  107. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js.map +1 -1
  108. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.d.ts.map +1 -1
  109. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js +1 -1
  110. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js.map +1 -1
  111. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js +8 -6
  112. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js.map +1 -1
  113. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.d.ts +1 -0
  114. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.d.ts.map +1 -1
  115. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.js.map +1 -1
  116. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js +109 -56
  117. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js.map +1 -1
  118. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.d.ts.map +1 -1
  119. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.js.map +1 -1
  120. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js +5 -3
  121. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js.map +1 -1
  122. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.d.ts.map +1 -1
  123. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.js.map +1 -1
  124. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js +6 -3
  125. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js.map +1 -1
  126. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.d.ts.map +1 -1
  127. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.js.map +1 -1
  128. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js +7 -5
  129. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js.map +1 -1
  130. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.d.ts +2 -2
  131. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.d.ts.map +1 -1
  132. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.js +1 -1
  133. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.js.map +1 -1
  134. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js +20 -15
  135. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js.map +1 -1
  136. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.d.ts.map +1 -1
  137. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.js +1 -1
  138. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.js.map +1 -1
  139. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js +4 -2
  140. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js.map +1 -1
  141. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.d.ts.map +1 -1
  142. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.js.map +1 -1
  143. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js +11 -6
  144. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js.map +1 -1
  145. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.d.ts +4 -0
  146. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.d.ts.map +1 -0
  147. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.js +100 -0
  148. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.js.map +1 -0
  149. package/dist/v2/blocks/response-block/helpers/response-stream.d.ts +13 -0
  150. package/dist/v2/blocks/response-block/helpers/response-stream.d.ts.map +1 -0
  151. package/dist/v2/blocks/response-block/helpers/response-stream.js +97 -0
  152. package/dist/v2/blocks/response-block/helpers/response-stream.js.map +1 -0
  153. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts +1 -1
  154. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
  155. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
  156. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
  157. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +39 -27
  158. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
  159. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.d.ts +6 -6
  160. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.d.ts.map +1 -1
  161. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js +1 -1
  162. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js.map +1 -1
  163. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js +7 -4
  164. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js.map +1 -1
  165. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.d.ts.map +1 -1
  166. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.js.map +1 -1
  167. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js +21 -16
  168. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js.map +1 -1
  169. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts.map +1 -1
  170. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.js.map +1 -1
  171. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js +7 -5
  172. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
  173. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.d.ts.map +1 -1
  174. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.js.map +1 -1
  175. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js +7 -5
  176. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js.map +1 -1
  177. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
  178. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
  179. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +105 -40
  180. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
  181. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.d.ts.map +1 -1
  182. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.js.map +1 -1
  183. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js +10 -8
  184. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js.map +1 -1
  185. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.d.ts.map +1 -1
  186. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.js.map +1 -1
  187. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js +14 -9
  188. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js.map +1 -1
  189. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.d.ts.map +1 -1
  190. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.js.map +1 -1
  191. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js +6 -4
  192. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js.map +1 -1
  193. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.d.ts.map +1 -1
  194. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.js.map +1 -1
  195. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js +3 -1
  196. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js.map +1 -1
  197. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
  198. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
  199. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +40 -40
  200. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
  201. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.d.ts +108 -7
  202. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.d.ts.map +1 -1
  203. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js +12 -0
  204. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js.map +1 -1
  205. package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts.map +1 -1
  206. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts.map +1 -1
  207. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js +8 -5
  208. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js.map +1 -1
  209. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts +2 -0
  210. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts.map +1 -1
  211. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js +2 -0
  212. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map +1 -1
  213. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts +3 -0
  214. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts.map +1 -0
  215. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js +8 -0
  216. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js.map +1 -0
  217. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.d.ts +3 -0
  218. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.d.ts.map +1 -0
  219. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.js +11 -0
  220. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.js.map +1 -0
  221. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts +19 -0
  222. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts.map +1 -0
  223. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js +117 -0
  224. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js.map +1 -0
  225. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts +2 -1
  226. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
  227. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +15 -11
  228. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
  229. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts +1 -1
  230. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts.map +1 -1
  231. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js +8 -1
  232. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js.map +1 -1
  233. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.d.ts.map +1 -1
  234. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js +6 -0
  235. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js.map +1 -1
  236. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts +2 -1
  237. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts.map +1 -1
  238. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js +8 -6
  239. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js.map +1 -1
  240. package/dist/v2/components/code-input/CodeInput.vue.d.ts +4 -4
  241. package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
  242. package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
  243. package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
  244. package/dist/v2/components/code-input/CodeInput.vue.script.js +10 -10
  245. package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
  246. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts +4 -4
  247. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
  248. package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
  249. package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -1
  250. package/dist/v2/components/code-input/CodeInputLite.vue.script.js +8 -5
  251. package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
  252. package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts +4 -0
  253. package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts.map +1 -1
  254. package/dist/v2/components/code-input/PillTooltipHost.vue.js.map +1 -1
  255. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js +7 -3
  256. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js.map +1 -1
  257. package/dist/v2/components/code-input/code-variable-widget.d.ts +3 -0
  258. package/dist/v2/components/code-input/code-variable-widget.d.ts.map +1 -1
  259. package/dist/v2/components/code-input/code-variable-widget.js +6 -3
  260. package/dist/v2/components/code-input/code-variable-widget.js.map +1 -1
  261. package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts +0 -1
  262. package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts.map +1 -1
  263. package/dist/v2/components/data-table/DataTableCheckbox.vue.js.map +1 -1
  264. package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js +4 -2
  265. package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js.map +1 -1
  266. package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
  267. package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
  268. package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
  269. package/dist/v2/components/data-table/DataTableInput.vue.script.js +5 -3
  270. package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
  271. package/dist/v2/components/data-table/DataTableInputSelect.vue.d.ts.map +1 -1
  272. package/dist/v2/components/data-table/DataTableInputSelect.vue.js.map +1 -1
  273. package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js +12 -9
  274. package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js.map +1 -1
  275. package/dist/v2/components/forms/ConfirmationForm.vue.d.ts.map +1 -1
  276. package/dist/v2/components/forms/ConfirmationForm.vue.js.map +1 -1
  277. package/dist/v2/components/forms/ConfirmationForm.vue.script.js +5 -3
  278. package/dist/v2/components/forms/ConfirmationForm.vue.script.js.map +1 -1
  279. package/dist/v2/components/layout/CollapsibleSection.vue.d.ts.map +1 -1
  280. package/dist/v2/components/layout/CollapsibleSection.vue.js.map +1 -1
  281. package/dist/v2/components/layout/CollapsibleSection.vue.script.js +3 -1
  282. package/dist/v2/components/layout/CollapsibleSection.vue.script.js.map +1 -1
  283. package/dist/v2/components/modals/DeleteModal.vue.d.ts.map +1 -1
  284. package/dist/v2/components/modals/DeleteModal.vue.js.map +1 -1
  285. package/dist/v2/components/modals/DeleteModal.vue.script.js +3 -1
  286. package/dist/v2/components/modals/DeleteModal.vue.script.js.map +1 -1
  287. package/dist/v2/components/modals/ModalClientContainer.vue.d.ts.map +1 -1
  288. package/dist/v2/components/modals/ModalClientContainer.vue.js +1 -1
  289. package/dist/v2/components/modals/ModalClientContainer.vue.js.map +1 -1
  290. package/dist/v2/components/modals/ModalClientContainer.vue.script.js +5 -2
  291. package/dist/v2/components/modals/ModalClientContainer.vue.script.js.map +1 -1
  292. package/dist/v2/components/server/ServerDropdown.vue.d.ts.map +1 -1
  293. package/dist/v2/components/server/ServerDropdown.vue.js.map +1 -1
  294. package/dist/v2/components/server/ServerDropdown.vue.script.js +9 -5
  295. package/dist/v2/components/server/ServerDropdown.vue.script.js.map +1 -1
  296. package/dist/v2/components/sidebar/Sidebar.vue.d.ts.map +1 -1
  297. package/dist/v2/components/sidebar/Sidebar.vue.js.map +1 -1
  298. package/dist/v2/components/sidebar/Sidebar.vue.script.js +4 -2
  299. package/dist/v2/components/sidebar/Sidebar.vue.script.js.map +1 -1
  300. package/dist/v2/components/sidebar/SidebarMenu.vue.d.ts.map +1 -1
  301. package/dist/v2/components/sidebar/SidebarMenu.vue.js.map +1 -1
  302. package/dist/v2/components/sidebar/SidebarMenu.vue.script.js +4 -2
  303. package/dist/v2/components/sidebar/SidebarMenu.vue.script.js.map +1 -1
  304. package/dist/v2/components/sidebar/SidebarToggle.vue.d.ts.map +1 -1
  305. package/dist/v2/components/sidebar/SidebarToggle.vue.js.map +1 -1
  306. package/dist/v2/components/sidebar/SidebarToggle.vue.script.js +4 -2
  307. package/dist/v2/components/sidebar/SidebarToggle.vue.script.js.map +1 -1
  308. package/dist/v2/constants.js +1 -1
  309. package/dist/v2/features/command-palette/components/CommandActionForm.vue.d.ts.map +1 -1
  310. package/dist/v2/features/command-palette/components/CommandActionForm.vue.js.map +1 -1
  311. package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js +4 -2
  312. package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js.map +1 -1
  313. package/dist/v2/features/command-palette/components/CommandActionInput.vue.d.ts +2 -2
  314. package/dist/v2/features/environments/EnvironmentsList.vue.d.ts.map +1 -1
  315. package/dist/v2/features/environments/EnvironmentsList.vue.js.map +1 -1
  316. package/dist/v2/features/environments/EnvironmentsList.vue.script.js +4 -2
  317. package/dist/v2/features/environments/EnvironmentsList.vue.script.js.map +1 -1
  318. package/dist/v2/features/environments/components/Environment.vue.d.ts.map +1 -1
  319. package/dist/v2/features/environments/components/Environment.vue.js.map +1 -1
  320. package/dist/v2/features/environments/components/Environment.vue.script.js +12 -10
  321. package/dist/v2/features/environments/components/Environment.vue.script.js.map +1 -1
  322. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.d.ts.map +1 -1
  323. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.js.map +1 -1
  324. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js +5 -3
  325. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js.map +1 -1
  326. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.d.ts.map +1 -1
  327. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.js.map +1 -1
  328. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js +9 -6
  329. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js.map +1 -1
  330. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.d.ts.map +1 -1
  331. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.js.map +1 -1
  332. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js +6 -4
  333. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js.map +1 -1
  334. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.d.ts.map +1 -1
  335. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js +1 -1
  336. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js.map +1 -1
  337. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js +22 -10
  338. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js.map +1 -1
  339. package/dist/v2/features/localization/index.d.ts +18 -0
  340. package/dist/v2/features/localization/index.d.ts.map +1 -0
  341. package/dist/v2/features/localization/index.js +35 -0
  342. package/dist/v2/features/localization/index.js.map +1 -0
  343. package/dist/v2/features/localization/locales/ar.d.ts +385 -0
  344. package/dist/v2/features/localization/locales/ar.d.ts.map +1 -0
  345. package/dist/v2/features/localization/locales/ar.js +345 -0
  346. package/dist/v2/features/localization/locales/ar.js.map +1 -0
  347. package/dist/v2/features/localization/locales/de.d.ts +385 -0
  348. package/dist/v2/features/localization/locales/de.d.ts.map +1 -0
  349. package/dist/v2/features/localization/locales/de.js +345 -0
  350. package/dist/v2/features/localization/locales/de.js.map +1 -0
  351. package/dist/v2/features/localization/locales/es.d.ts +385 -0
  352. package/dist/v2/features/localization/locales/es.d.ts.map +1 -0
  353. package/dist/v2/features/localization/locales/es.js +345 -0
  354. package/dist/v2/features/localization/locales/es.js.map +1 -0
  355. package/dist/v2/features/localization/locales/fr.d.ts +385 -0
  356. package/dist/v2/features/localization/locales/fr.d.ts.map +1 -0
  357. package/dist/v2/features/localization/locales/fr.js +345 -0
  358. package/dist/v2/features/localization/locales/fr.js.map +1 -0
  359. package/dist/v2/features/localization/locales/pt.d.ts +385 -0
  360. package/dist/v2/features/localization/locales/pt.d.ts.map +1 -0
  361. package/dist/v2/features/localization/locales/pt.js +345 -0
  362. package/dist/v2/features/localization/locales/pt.js.map +1 -0
  363. package/dist/v2/features/localization/locales/ru.d.ts +385 -0
  364. package/dist/v2/features/localization/locales/ru.d.ts.map +1 -0
  365. package/dist/v2/features/localization/locales/ru.js +345 -0
  366. package/dist/v2/features/localization/locales/ru.js.map +1 -0
  367. package/dist/v2/features/localization/locales/zh-cn.d.ts +385 -0
  368. package/dist/v2/features/localization/locales/zh-cn.d.ts.map +1 -0
  369. package/dist/v2/features/localization/locales/zh-cn.js +345 -0
  370. package/dist/v2/features/localization/locales/zh-cn.js.map +1 -0
  371. package/dist/v2/features/localization/translations.d.ts +385 -0
  372. package/dist/v2/features/localization/translations.d.ts.map +1 -0
  373. package/dist/v2/features/localization/translations.js +345 -0
  374. package/dist/v2/features/localization/translations.js.map +1 -0
  375. package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
  376. package/dist/v2/features/modal/Modal.vue.js.map +1 -1
  377. package/dist/v2/features/modal/Modal.vue.script.js +15 -4
  378. package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
  379. package/dist/v2/features/modal/use-lazy-api-client.d.ts +11 -0
  380. package/dist/v2/features/modal/use-lazy-api-client.d.ts.map +1 -0
  381. package/dist/v2/features/modal/use-lazy-api-client.js +48 -0
  382. package/dist/v2/features/modal/use-lazy-api-client.js.map +1 -0
  383. package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
  384. package/dist/v2/features/operation/Operation.vue.js.map +1 -1
  385. package/dist/v2/features/operation/Operation.vue.script.js +22 -6
  386. package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
  387. package/dist/v2/features/search/components/DocumentSearchModal.vue.d.ts.map +1 -1
  388. package/dist/v2/features/search/components/DocumentSearchModal.vue.js +1 -1
  389. package/dist/v2/features/search/components/DocumentSearchModal.vue.js.map +1 -1
  390. package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js +12 -8
  391. package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js.map +1 -1
  392. package/dist/v2/features/search/components/SearchResult.vue.d.ts.map +1 -1
  393. package/dist/v2/features/search/components/SearchResult.vue.js.map +1 -1
  394. package/dist/v2/features/search/components/SearchResult.vue.script.js +14 -10
  395. package/dist/v2/features/search/components/SearchResult.vue.script.js.map +1 -1
  396. package/dist/v2/types/options.d.ts +1 -1
  397. package/dist/v2/types/options.d.ts.map +1 -1
  398. package/dist/v2/workspace-events.d.ts +2 -2
  399. package/dist/v2/workspace-events.d.ts.map +1 -1
  400. package/dist/v2/workspace-events.js +8 -1
  401. package/dist/v2/workspace-events.js.map +1 -1
  402. package/dist/vue-styles.css +124 -125
  403. package/package.json +22 -11
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyPreview.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyPreview.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed, ref, watch } from 'vue'\n\nimport { type MediaPreview } from '@/v2/blocks/response-block/helpers/media-types'\nimport { prettifyNdjson } from '@/v2/blocks/response-block/helpers/prettify-ndjson'\n\nimport ResponseBodyInfo from './ResponseBodyInfo.vue'\nimport ResponseBodyRaw from './ResponseBodyRaw.vue'\n\nconst {\n src,\n type,\n mode,\n alpha = false,\n content,\n} = defineProps<{\n src: string\n type: string\n mode: MediaPreview\n alpha?: boolean | undefined\n /** Decoded body; used when `mode` is `json` for pretty-printed preview (no JSON.parse round-trip). */\n content?: unknown\n}>()\n\nconst jsonPreviewContent = computed((): string => {\n const value = content\n if (typeof value === 'string') {\n return value\n }\n if (value == null) {\n return ''\n }\n return String(value)\n})\n\n/** NDJSON pretty-printed one record per block for the `ndjson` preview. */\nconst ndjsonPreviewContent = computed((): string =>\n prettifyNdjson(jsonPreviewContent.value),\n)\n\n/**\n * Validates the `src` against an allow-list of safe protocols before it is\n * passed to a rendering element. This blocks XSS vectors such as\n * `javascript:` and `vbscript:` URIs and also prevents accidentally embedding\n * a `data:text/html` payload that could execute script in the app origin.\n *\n * Allowed:\n * - `blob:` (the standard case — generated client-side by `URL.createObjectURL`)\n * - `http:` / `https:`\n * - `data:` URIs whose MIME type is a known safe media kind\n * (`image/*`, `video/*`, `audio/*`, `application/pdf`, `application/octet-stream`)\n *\n * Anything else (including malformed or relative URLs) collapses to an empty\n * string so the template falls back to the \"Preview unavailable\" message.\n */\nconst safeSrc = computed((): string => {\n if (!src) {\n return ''\n }\n\n if (/^data:/i.test(src)) {\n // The MIME type must be one of the known safe kinds AND be terminated by\n // `;` (parameters / `;base64`) or `,` (start of the payload). Anchoring\n // at the terminator prevents prefix-matching tricks like\n // `data:image/png-but-actually-html,…`.\n return /^data:(?:(?:image|video|audio)\\/[a-z0-9.+-]+|application\\/pdf|application\\/octet-stream)[;,]/i.test(\n src,\n )\n ? src\n : ''\n }\n\n try {\n const parsed = new URL(src)\n if (\n parsed.protocol === 'blob:' ||\n parsed.protocol === 'http:' ||\n parsed.protocol === 'https:'\n ) {\n return src\n }\n } catch {\n // Malformed or relative URL — refuse to render.\n }\n\n return ''\n})\n\nconst error = ref(false)\n\n/**\n * Whether the embedded document is a PDF.\n *\n * PDFs are rendered by the browser's own PDF engine (e.g. PDFium), which runs\n * in an isolated context that cannot reach this app's origin — its DOM,\n * cookies or storage. A PDF's embedded JavaScript therefore cannot be used to\n * attack us, and a strict `sandbox=\"\"` does not confine that engine; it only\n * prevents Chromium from loading the PDF viewer at all (it boots as a scripted\n * extension page), leaving the user with a blank frame. So PDFs are rendered\n * without the `sandbox` attribute, matching the original `<object>` behaviour.\n *\n * Everything else that reaches the iframe (notably `text/html`, the genuine\n * XSS vector) keeps the strict empty sandbox.\n */\nconst isPdf = computed(\n (): boolean => type.trim().toLowerCase() === 'application/pdf',\n)\n\nwatch(\n () => src,\n () => (error.value = false),\n)\n</script>\n<template>\n <ResponseBodyRaw\n v-if=\"mode === 'json'\"\n :content=\"jsonPreviewContent\"\n language=\"json\"\n prettyPrintJson />\n <ResponseBodyRaw\n v-else-if=\"mode === 'ndjson'\"\n :content=\"ndjsonPreviewContent\"\n language=\"json\" />\n <div\n v-else-if=\"!error && safeSrc\"\n class=\"flex justify-center overflow-auto rounded-b\"\n :class=\"{ 'bg-preview p-2': alpha }\">\n <img\n v-if=\"mode === 'image'\"\n class=\"h-full max-w-full\"\n :class=\"{ rounded: alpha }\"\n :src=\"safeSrc\"\n referrerpolicy=\"no-referrer\"\n @error=\"error = true\" />\n <video\n v-else-if=\"mode === 'video'\"\n autoplay\n controls\n referrerpolicy=\"no-referrer\"\n width=\"100%\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </video>\n <audio\n v-else-if=\"mode === 'audio'\"\n class=\"my-12\"\n controls\n referrerpolicy=\"no-referrer\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </audio>\n <!--\n `<object>` would execute scripts inside the embedded document in the\n app's origin, so we render arbitrary previews inside an `<iframe>`\n instead. Non-PDF documents (notably `text/html`) get an empty `sandbox`\n attribute, which disables scripts, forms, popups and same-origin access.\n PDFs are exempted (see `isPdf` above): the empty sandbox does not confine\n the browser's PDF engine, it only stops the viewer from loading at all.\n\n Note: an `error` event on `<iframe>` is not reliably fired for failed\n navigations — browsers usually fire `load` even when the response is\n blank or an error page, and a cross-origin sandboxed frame cannot be\n introspected from JavaScript. There is therefore no useful runtime\n fallback for an unreachable URL; the URL allow-list above is what\n keeps unsafe content out in the first place.\n -->\n <iframe\n v-else\n class=\"aspect-[4/3] w-full border-0\"\n :src=\"safeSrc\"\n :sandbox=\"isPdf ? undefined : ''\"\n referrerpolicy=\"no-referrer\" />\n </div>\n <ResponseBodyInfo v-else>Preview unavailable</ResponseBodyInfo>\n</template>\n<style scoped>\n.light-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23000' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n.dark-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23FFF' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ResponseBodyPreview.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyPreview.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed, ref, watch } from 'vue'\n\nimport { type MediaPreview } from '@/v2/blocks/response-block/helpers/media-types'\nimport { prettifyNdjson } from '@/v2/blocks/response-block/helpers/prettify-ndjson'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport ResponseBodyInfo from './ResponseBodyInfo.vue'\nimport ResponseBodyRaw from './ResponseBodyRaw.vue'\n\nconst {\n src,\n type,\n mode,\n alpha = false,\n content,\n} = defineProps<{\n src: string\n type: string\n mode: MediaPreview\n alpha?: boolean | undefined\n /** Decoded body; used when `mode` is `json` for pretty-printed preview (no JSON.parse round-trip). */\n content?: unknown\n}>()\n\nconst { translate } = useLocalization()\n\nconst jsonPreviewContent = computed((): string => {\n const value = content\n if (typeof value === 'string') {\n return value\n }\n if (value == null) {\n return ''\n }\n return String(value)\n})\n\n/** NDJSON pretty-printed one record per block for the `ndjson` preview. */\nconst ndjsonPreviewContent = computed((): string =>\n prettifyNdjson(jsonPreviewContent.value),\n)\n\n/**\n * Validates the `src` against an allow-list of safe protocols before it is\n * passed to a rendering element. This blocks XSS vectors such as\n * `javascript:` and `vbscript:` URIs and also prevents accidentally embedding\n * a `data:text/html` payload that could execute script in the app origin.\n *\n * Allowed:\n * - `blob:` (the standard case — generated client-side by `URL.createObjectURL`)\n * - `http:` / `https:`\n * - `data:` URIs whose MIME type is a known safe media kind\n * (`image/*`, `video/*`, `audio/*`, `application/pdf`, `application/octet-stream`)\n *\n * Anything else (including malformed or relative URLs) collapses to an empty\n * string so the template falls back to the \"Preview unavailable\" message.\n */\nconst safeSrc = computed((): string => {\n if (!src) {\n return ''\n }\n\n if (/^data:/i.test(src)) {\n // The MIME type must be one of the known safe kinds AND be terminated by\n // `;` (parameters / `;base64`) or `,` (start of the payload). Anchoring\n // at the terminator prevents prefix-matching tricks like\n // `data:image/png-but-actually-html,…`.\n return /^data:(?:(?:image|video|audio)\\/[a-z0-9.+-]+|application\\/pdf|application\\/octet-stream)[;,]/i.test(\n src,\n )\n ? src\n : ''\n }\n\n try {\n const parsed = new URL(src)\n if (\n parsed.protocol === 'blob:' ||\n parsed.protocol === 'http:' ||\n parsed.protocol === 'https:'\n ) {\n return src\n }\n } catch {\n // Malformed or relative URL — refuse to render.\n }\n\n return ''\n})\n\nconst error = ref(false)\n\n/**\n * Whether the embedded document is a PDF.\n *\n * PDFs are rendered by the browser's own PDF engine (e.g. PDFium), which runs\n * in an isolated context that cannot reach this app's origin — its DOM,\n * cookies or storage. A PDF's embedded JavaScript therefore cannot be used to\n * attack us, and a strict `sandbox=\"\"` does not confine that engine; it only\n * prevents Chromium from loading the PDF viewer at all (it boots as a scripted\n * extension page), leaving the user with a blank frame. So PDFs are rendered\n * without the `sandbox` attribute, matching the original `<object>` behaviour.\n *\n * Everything else that reaches the iframe (notably `text/html`, the genuine\n * XSS vector) keeps the strict empty sandbox.\n */\nconst isPdf = computed(\n (): boolean => type.trim().toLowerCase() === 'application/pdf',\n)\n\nwatch(\n () => src,\n () => (error.value = false),\n)\n</script>\n<template>\n <ResponseBodyRaw\n v-if=\"mode === 'json'\"\n :content=\"jsonPreviewContent\"\n language=\"json\"\n prettyPrintJson />\n <ResponseBodyRaw\n v-else-if=\"mode === 'ndjson'\"\n :content=\"ndjsonPreviewContent\"\n language=\"json\" />\n <div\n v-else-if=\"!error && safeSrc\"\n class=\"flex justify-center overflow-auto rounded-b\"\n :class=\"{ 'bg-preview p-2': alpha }\">\n <img\n v-if=\"mode === 'image'\"\n class=\"h-full max-w-full\"\n :class=\"{ rounded: alpha }\"\n referrerpolicy=\"no-referrer\"\n :src=\"safeSrc\"\n @error=\"error = true\" />\n <video\n v-else-if=\"mode === 'video'\"\n autoplay\n controls\n referrerpolicy=\"no-referrer\"\n width=\"100%\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </video>\n <audio\n v-else-if=\"mode === 'audio'\"\n class=\"my-12\"\n controls\n referrerpolicy=\"no-referrer\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </audio>\n <!--\n `<object>` would execute scripts inside the embedded document in the\n app's origin, so we render arbitrary previews inside an `<iframe>`\n instead. Non-PDF documents (notably `text/html`) get an empty `sandbox`\n attribute, which disables scripts, forms, popups and same-origin access.\n PDFs are exempted (see `isPdf` above): the empty sandbox does not confine\n the browser's PDF engine, it only stops the viewer from loading at all.\n\n Note: an `error` event on `<iframe>` is not reliably fired for failed\n navigations — browsers usually fire `load` even when the response is\n blank or an error page, and a cross-origin sandboxed frame cannot be\n introspected from JavaScript. There is therefore no useful runtime\n fallback for an unreachable URL; the URL allow-list above is what\n keeps unsafe content out in the first place.\n -->\n <iframe\n v-else\n class=\"aspect-[4/3] w-full border-0\"\n referrerpolicy=\"no-referrer\"\n :sandbox=\"isPdf ? undefined : ''\"\n :src=\"safeSrc\" />\n </div>\n <ResponseBodyInfo v-else>\n {{ translate('apiClient.responseBodyPreview.previewUnavailable') }}\n </ResponseBodyInfo>\n</template>\n<style scoped>\n.light-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23000' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n.dark-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23FFF' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n</style>\n"],"mappings":""}
@@ -1,12 +1,13 @@
1
+ import { useLocalization } from "../../../features/localization/index.js";
1
2
  import ResponseBodyInfo_default from "./ResponseBodyInfo.vue.js";
2
3
  import { prettifyNdjson } from "../helpers/prettify-ndjson.js";
3
4
  import ResponseBodyRaw_default from "./ResponseBodyRaw.vue.js";
4
- import { computed, createBlock, createElementBlock, createElementVNode, createTextVNode, defineComponent, normalizeClass, openBlock, ref, watch, withCtx } from "vue";
5
+ import { computed, createBlock, createElementBlock, createElementVNode, createTextVNode, defineComponent, normalizeClass, openBlock, ref, toDisplayString, unref, watch, withCtx } from "vue";
5
6
  //#region src/v2/blocks/response-block/components/ResponseBodyPreview.vue?vue&type=script&setup=true&lang.ts
6
7
  var _hoisted_1 = ["src"];
7
8
  var _hoisted_2 = ["src", "type"];
8
9
  var _hoisted_3 = ["src", "type"];
9
- var _hoisted_4 = ["src", "sandbox"];
10
+ var _hoisted_4 = ["sandbox", "src"];
10
11
  var ResponseBodyPreview_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
11
12
  __name: "ResponseBodyPreview",
12
13
  props: {
@@ -20,6 +21,7 @@ var ResponseBodyPreview_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
20
21
  content: {}
21
22
  },
22
23
  setup(__props) {
24
+ const { translate } = useLocalization();
23
25
  const jsonPreviewContent = computed(() => {
24
26
  const value = __props.content;
25
27
  if (typeof value === "string") return value;
@@ -85,8 +87,8 @@ var ResponseBodyPreview_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
85
87
  }, [__props.mode === "image" ? (openBlock(), createElementBlock("img", {
86
88
  key: 0,
87
89
  class: normalizeClass(["h-full max-w-full", { rounded: __props.alpha }]),
88
- src: safeSrc.value,
89
90
  referrerpolicy: "no-referrer",
91
+ src: safeSrc.value,
90
92
  onError: _cache[0] || (_cache[0] = ($event) => error.value = true)
91
93
  }, null, 42, _hoisted_1)) : __props.mode === "video" ? (openBlock(), createElementBlock("video", {
92
94
  key: 1,
@@ -110,11 +112,11 @@ var ResponseBodyPreview_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
110
112
  }, null, 8, _hoisted_3)], 32)) : (openBlock(), createElementBlock("iframe", {
111
113
  key: 3,
112
114
  class: "aspect-[4/3] w-full border-0",
113
- src: safeSrc.value,
115
+ referrerpolicy: "no-referrer",
114
116
  sandbox: isPdf.value ? void 0 : "",
115
- referrerpolicy: "no-referrer"
117
+ src: safeSrc.value
116
118
  }, null, 8, _hoisted_4))], 2)) : (openBlock(), createBlock(ResponseBodyInfo_default, { key: 3 }, {
117
- default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode("Preview unavailable", -1)])]),
119
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.responseBodyPreview.previewUnavailable")), 1)]),
118
120
  _: 1
119
121
  }));
120
122
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyPreview.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyPreview.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed, ref, watch } from 'vue'\n\nimport { type MediaPreview } from '@/v2/blocks/response-block/helpers/media-types'\nimport { prettifyNdjson } from '@/v2/blocks/response-block/helpers/prettify-ndjson'\n\nimport ResponseBodyInfo from './ResponseBodyInfo.vue'\nimport ResponseBodyRaw from './ResponseBodyRaw.vue'\n\nconst {\n src,\n type,\n mode,\n alpha = false,\n content,\n} = defineProps<{\n src: string\n type: string\n mode: MediaPreview\n alpha?: boolean | undefined\n /** Decoded body; used when `mode` is `json` for pretty-printed preview (no JSON.parse round-trip). */\n content?: unknown\n}>()\n\nconst jsonPreviewContent = computed((): string => {\n const value = content\n if (typeof value === 'string') {\n return value\n }\n if (value == null) {\n return ''\n }\n return String(value)\n})\n\n/** NDJSON pretty-printed one record per block for the `ndjson` preview. */\nconst ndjsonPreviewContent = computed((): string =>\n prettifyNdjson(jsonPreviewContent.value),\n)\n\n/**\n * Validates the `src` against an allow-list of safe protocols before it is\n * passed to a rendering element. This blocks XSS vectors such as\n * `javascript:` and `vbscript:` URIs and also prevents accidentally embedding\n * a `data:text/html` payload that could execute script in the app origin.\n *\n * Allowed:\n * - `blob:` (the standard case — generated client-side by `URL.createObjectURL`)\n * - `http:` / `https:`\n * - `data:` URIs whose MIME type is a known safe media kind\n * (`image/*`, `video/*`, `audio/*`, `application/pdf`, `application/octet-stream`)\n *\n * Anything else (including malformed or relative URLs) collapses to an empty\n * string so the template falls back to the \"Preview unavailable\" message.\n */\nconst safeSrc = computed((): string => {\n if (!src) {\n return ''\n }\n\n if (/^data:/i.test(src)) {\n // The MIME type must be one of the known safe kinds AND be terminated by\n // `;` (parameters / `;base64`) or `,` (start of the payload). Anchoring\n // at the terminator prevents prefix-matching tricks like\n // `data:image/png-but-actually-html,…`.\n return /^data:(?:(?:image|video|audio)\\/[a-z0-9.+-]+|application\\/pdf|application\\/octet-stream)[;,]/i.test(\n src,\n )\n ? src\n : ''\n }\n\n try {\n const parsed = new URL(src)\n if (\n parsed.protocol === 'blob:' ||\n parsed.protocol === 'http:' ||\n parsed.protocol === 'https:'\n ) {\n return src\n }\n } catch {\n // Malformed or relative URL — refuse to render.\n }\n\n return ''\n})\n\nconst error = ref(false)\n\n/**\n * Whether the embedded document is a PDF.\n *\n * PDFs are rendered by the browser's own PDF engine (e.g. PDFium), which runs\n * in an isolated context that cannot reach this app's origin — its DOM,\n * cookies or storage. A PDF's embedded JavaScript therefore cannot be used to\n * attack us, and a strict `sandbox=\"\"` does not confine that engine; it only\n * prevents Chromium from loading the PDF viewer at all (it boots as a scripted\n * extension page), leaving the user with a blank frame. So PDFs are rendered\n * without the `sandbox` attribute, matching the original `<object>` behaviour.\n *\n * Everything else that reaches the iframe (notably `text/html`, the genuine\n * XSS vector) keeps the strict empty sandbox.\n */\nconst isPdf = computed(\n (): boolean => type.trim().toLowerCase() === 'application/pdf',\n)\n\nwatch(\n () => src,\n () => (error.value = false),\n)\n</script>\n<template>\n <ResponseBodyRaw\n v-if=\"mode === 'json'\"\n :content=\"jsonPreviewContent\"\n language=\"json\"\n prettyPrintJson />\n <ResponseBodyRaw\n v-else-if=\"mode === 'ndjson'\"\n :content=\"ndjsonPreviewContent\"\n language=\"json\" />\n <div\n v-else-if=\"!error && safeSrc\"\n class=\"flex justify-center overflow-auto rounded-b\"\n :class=\"{ 'bg-preview p-2': alpha }\">\n <img\n v-if=\"mode === 'image'\"\n class=\"h-full max-w-full\"\n :class=\"{ rounded: alpha }\"\n :src=\"safeSrc\"\n referrerpolicy=\"no-referrer\"\n @error=\"error = true\" />\n <video\n v-else-if=\"mode === 'video'\"\n autoplay\n controls\n referrerpolicy=\"no-referrer\"\n width=\"100%\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </video>\n <audio\n v-else-if=\"mode === 'audio'\"\n class=\"my-12\"\n controls\n referrerpolicy=\"no-referrer\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </audio>\n <!--\n `<object>` would execute scripts inside the embedded document in the\n app's origin, so we render arbitrary previews inside an `<iframe>`\n instead. Non-PDF documents (notably `text/html`) get an empty `sandbox`\n attribute, which disables scripts, forms, popups and same-origin access.\n PDFs are exempted (see `isPdf` above): the empty sandbox does not confine\n the browser's PDF engine, it only stops the viewer from loading at all.\n\n Note: an `error` event on `<iframe>` is not reliably fired for failed\n navigations — browsers usually fire `load` even when the response is\n blank or an error page, and a cross-origin sandboxed frame cannot be\n introspected from JavaScript. There is therefore no useful runtime\n fallback for an unreachable URL; the URL allow-list above is what\n keeps unsafe content out in the first place.\n -->\n <iframe\n v-else\n class=\"aspect-[4/3] w-full border-0\"\n :src=\"safeSrc\"\n :sandbox=\"isPdf ? undefined : ''\"\n referrerpolicy=\"no-referrer\" />\n </div>\n <ResponseBodyInfo v-else>Preview unavailable</ResponseBodyInfo>\n</template>\n<style scoped>\n.light-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23000' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n.dark-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23FFF' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAwBA,MAAM,qBAAqB,eAAuB;GAChD,MAAM,QAAQ,QAAA;GACd,IAAI,OAAO,UAAU,UACnB,OAAO;GAET,IAAI,SAAS,MACX,OAAO;GAET,OAAO,OAAO,KAAK;EACrB,CAAC;;EAGD,MAAM,uBAAuB,eAC3B,eAAe,mBAAmB,KAAK,CACzC;;;;;;;;;;;;;;;;EAiBA,MAAM,UAAU,eAAuB;GACrC,IAAI,CAAC,QAAA,KACH,OAAO;GAGT,IAAI,UAAU,KAAK,QAAA,GAAG,GAKpB,OAAO,gGAAgG,KACrG,QAAA,GACF,IACI,QAAA,MACA;GAGN,IAAI;IACF,MAAM,SAAS,IAAI,IAAI,QAAA,GAAG;IAC1B,IACE,OAAO,aAAa,WACpB,OAAO,aAAa,WACpB,OAAO,aAAa,UAEpB,OAAO,QAAA;GAEX,QAAQ,CAER;GAEA,OAAO;EACT,CAAC;EAED,MAAM,QAAQ,IAAI,KAAK;;;;;;;;;;;;;;;EAgBvB,MAAM,QAAQ,eACG,QAAA,KAAK,KAAK,CAAC,CAAC,YAAY,MAAM,iBAC/C;EAEA,YACQ,QAAA,WACC,MAAM,QAAQ,KACvB;;UAIU,QAAA,SAAI,UAAA,UAAA,GADZ,YAIoB,yBAAA;;IAFjB,SAAS,mBAAA;IACV,UAAS;IACT,iBAAA;+BAEW,QAAA,SAAI,YAAA,UAAA,GADjB,YAGoB,yBAAA;;IADjB,SAAS,qBAAA;IACV,UAAS;gCAEG,MAAA,SAAS,QAAA,SAAA,UAAA,GADvB,mBAqDM,OAAA;;IAnDJ,OAAK,eAAA,CAAC,+CAA6C,EAAA,kBACvB,QAAA,MAAK,CAAA,CAAA;OAEzB,QAAA,SAAI,WAAA,UAAA,GADZ,mBAM0B,OAAA;;IAJxB,OAAK,eAAA,CAAC,qBAAmB,EAAA,SACN,QAAA,MAAK,CAAA,CAAA;IACvB,KAAK,QAAA;IACN,gBAAe;IACd,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK;+BAEF,QAAA,SAAI,WAAA,UAAA,GADjB,mBAUQ,SAAA;;IARN,UAAA;IACA,UAAA;IACA,gBAAe;IACf,OAAM;IACL,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK;OACb,mBAEiB,UAAA;IADd,KAAK,QAAA;IACL,MAAM,QAAA;oCAGE,QAAA,SAAI,WAAA,UAAA,GADjB,mBASQ,SAAA;;IAPN,OAAM;IACN,UAAA;IACA,gBAAe;IACd,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK;OACb,mBAEiB,UAAA;IADd,KAAK,QAAA;IACL,MAAM,QAAA;kDAiBX,mBAKiC,UAAA;;IAH/B,OAAM;IACL,KAAK,QAAA;IACL,SAAS,MAAA,QAAQ,KAAA,IAAS;IAC3B,gBAAe;kDAEnB,YAA+D,0BAAA,EAAA,KAAA,EAAA,GAAA;2BAAnB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAnB,uBAAmB,EAAA,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"ResponseBodyPreview.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyPreview.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed, ref, watch } from 'vue'\n\nimport { type MediaPreview } from '@/v2/blocks/response-block/helpers/media-types'\nimport { prettifyNdjson } from '@/v2/blocks/response-block/helpers/prettify-ndjson'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport ResponseBodyInfo from './ResponseBodyInfo.vue'\nimport ResponseBodyRaw from './ResponseBodyRaw.vue'\n\nconst {\n src,\n type,\n mode,\n alpha = false,\n content,\n} = defineProps<{\n src: string\n type: string\n mode: MediaPreview\n alpha?: boolean | undefined\n /** Decoded body; used when `mode` is `json` for pretty-printed preview (no JSON.parse round-trip). */\n content?: unknown\n}>()\n\nconst { translate } = useLocalization()\n\nconst jsonPreviewContent = computed((): string => {\n const value = content\n if (typeof value === 'string') {\n return value\n }\n if (value == null) {\n return ''\n }\n return String(value)\n})\n\n/** NDJSON pretty-printed one record per block for the `ndjson` preview. */\nconst ndjsonPreviewContent = computed((): string =>\n prettifyNdjson(jsonPreviewContent.value),\n)\n\n/**\n * Validates the `src` against an allow-list of safe protocols before it is\n * passed to a rendering element. This blocks XSS vectors such as\n * `javascript:` and `vbscript:` URIs and also prevents accidentally embedding\n * a `data:text/html` payload that could execute script in the app origin.\n *\n * Allowed:\n * - `blob:` (the standard case — generated client-side by `URL.createObjectURL`)\n * - `http:` / `https:`\n * - `data:` URIs whose MIME type is a known safe media kind\n * (`image/*`, `video/*`, `audio/*`, `application/pdf`, `application/octet-stream`)\n *\n * Anything else (including malformed or relative URLs) collapses to an empty\n * string so the template falls back to the \"Preview unavailable\" message.\n */\nconst safeSrc = computed((): string => {\n if (!src) {\n return ''\n }\n\n if (/^data:/i.test(src)) {\n // The MIME type must be one of the known safe kinds AND be terminated by\n // `;` (parameters / `;base64`) or `,` (start of the payload). Anchoring\n // at the terminator prevents prefix-matching tricks like\n // `data:image/png-but-actually-html,…`.\n return /^data:(?:(?:image|video|audio)\\/[a-z0-9.+-]+|application\\/pdf|application\\/octet-stream)[;,]/i.test(\n src,\n )\n ? src\n : ''\n }\n\n try {\n const parsed = new URL(src)\n if (\n parsed.protocol === 'blob:' ||\n parsed.protocol === 'http:' ||\n parsed.protocol === 'https:'\n ) {\n return src\n }\n } catch {\n // Malformed or relative URL — refuse to render.\n }\n\n return ''\n})\n\nconst error = ref(false)\n\n/**\n * Whether the embedded document is a PDF.\n *\n * PDFs are rendered by the browser's own PDF engine (e.g. PDFium), which runs\n * in an isolated context that cannot reach this app's origin — its DOM,\n * cookies or storage. A PDF's embedded JavaScript therefore cannot be used to\n * attack us, and a strict `sandbox=\"\"` does not confine that engine; it only\n * prevents Chromium from loading the PDF viewer at all (it boots as a scripted\n * extension page), leaving the user with a blank frame. So PDFs are rendered\n * without the `sandbox` attribute, matching the original `<object>` behaviour.\n *\n * Everything else that reaches the iframe (notably `text/html`, the genuine\n * XSS vector) keeps the strict empty sandbox.\n */\nconst isPdf = computed(\n (): boolean => type.trim().toLowerCase() === 'application/pdf',\n)\n\nwatch(\n () => src,\n () => (error.value = false),\n)\n</script>\n<template>\n <ResponseBodyRaw\n v-if=\"mode === 'json'\"\n :content=\"jsonPreviewContent\"\n language=\"json\"\n prettyPrintJson />\n <ResponseBodyRaw\n v-else-if=\"mode === 'ndjson'\"\n :content=\"ndjsonPreviewContent\"\n language=\"json\" />\n <div\n v-else-if=\"!error && safeSrc\"\n class=\"flex justify-center overflow-auto rounded-b\"\n :class=\"{ 'bg-preview p-2': alpha }\">\n <img\n v-if=\"mode === 'image'\"\n class=\"h-full max-w-full\"\n :class=\"{ rounded: alpha }\"\n referrerpolicy=\"no-referrer\"\n :src=\"safeSrc\"\n @error=\"error = true\" />\n <video\n v-else-if=\"mode === 'video'\"\n autoplay\n controls\n referrerpolicy=\"no-referrer\"\n width=\"100%\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </video>\n <audio\n v-else-if=\"mode === 'audio'\"\n class=\"my-12\"\n controls\n referrerpolicy=\"no-referrer\"\n @error=\"error = true\">\n <source\n :src=\"safeSrc\"\n :type=\"type\" />\n </audio>\n <!--\n `<object>` would execute scripts inside the embedded document in the\n app's origin, so we render arbitrary previews inside an `<iframe>`\n instead. Non-PDF documents (notably `text/html`) get an empty `sandbox`\n attribute, which disables scripts, forms, popups and same-origin access.\n PDFs are exempted (see `isPdf` above): the empty sandbox does not confine\n the browser's PDF engine, it only stops the viewer from loading at all.\n\n Note: an `error` event on `<iframe>` is not reliably fired for failed\n navigations — browsers usually fire `load` even when the response is\n blank or an error page, and a cross-origin sandboxed frame cannot be\n introspected from JavaScript. There is therefore no useful runtime\n fallback for an unreachable URL; the URL allow-list above is what\n keeps unsafe content out in the first place.\n -->\n <iframe\n v-else\n class=\"aspect-[4/3] w-full border-0\"\n referrerpolicy=\"no-referrer\"\n :sandbox=\"isPdf ? undefined : ''\"\n :src=\"safeSrc\" />\n </div>\n <ResponseBodyInfo v-else>\n {{ translate('apiClient.responseBodyPreview.previewUnavailable') }}\n </ResponseBodyInfo>\n</template>\n<style scoped>\n.light-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23000' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n.dark-mode .bg-preview {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23FFF' fill-opacity='10%25'%3E%3Crect width='8' height='8' /%3E%3Crect x='8' y='8' width='8' height='8' /%3E%3C/svg%3E\");\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAyBA,MAAM,EAAE,cAAc,gBAAgB;EAEtC,MAAM,qBAAqB,eAAuB;GAChD,MAAM,QAAQ,QAAA;GACd,IAAI,OAAO,UAAU,UACnB,OAAO;GAET,IAAI,SAAS,MACX,OAAO;GAET,OAAO,OAAO,KAAK;EACrB,CAAC;;EAGD,MAAM,uBAAuB,eAC3B,eAAe,mBAAmB,KAAK,CACzC;;;;;;;;;;;;;;;;EAiBA,MAAM,UAAU,eAAuB;GACrC,IAAI,CAAC,QAAA,KACH,OAAO;GAGT,IAAI,UAAU,KAAK,QAAA,GAAG,GAKpB,OAAO,gGAAgG,KACrG,QAAA,GACF,IACI,QAAA,MACA;GAGN,IAAI;IACF,MAAM,SAAS,IAAI,IAAI,QAAA,GAAG;IAC1B,IACE,OAAO,aAAa,WACpB,OAAO,aAAa,WACpB,OAAO,aAAa,UAEpB,OAAO,QAAA;GAEX,QAAQ,CAER;GAEA,OAAO;EACT,CAAC;EAED,MAAM,QAAQ,IAAI,KAAK;;;;;;;;;;;;;;;EAgBvB,MAAM,QAAQ,eACG,QAAA,KAAK,KAAK,CAAC,CAAC,YAAY,MAAM,iBAC/C;EAEA,YACQ,QAAA,WACC,MAAM,QAAQ,KACvB;;UAIU,QAAA,SAAI,UAAA,UAAA,GADZ,YAIoB,yBAAA;;IAFjB,SAAS,mBAAA;IACV,UAAS;IACT,iBAAA;+BAEW,QAAA,SAAI,YAAA,UAAA,GADjB,YAGoB,yBAAA;;IADjB,SAAS,qBAAA;IACV,UAAS;gCAEG,MAAA,SAAS,QAAA,SAAA,UAAA,GADvB,mBAqDM,OAAA;;IAnDJ,OAAK,eAAA,CAAC,+CAA6C,EAAA,kBACvB,QAAA,MAAK,CAAA,CAAA;OAEzB,QAAA,SAAI,WAAA,UAAA,GADZ,mBAM0B,OAAA;;IAJxB,OAAK,eAAA,CAAC,qBAAmB,EAAA,SACN,QAAA,MAAK,CAAA,CAAA;IACxB,gBAAe;IACd,KAAK,QAAA;IACL,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK;+BAEF,QAAA,SAAI,WAAA,UAAA,GADjB,mBAUQ,SAAA;;IARN,UAAA;IACA,UAAA;IACA,gBAAe;IACf,OAAM;IACL,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK;OACb,mBAEiB,UAAA;IADd,KAAK,QAAA;IACL,MAAM,QAAA;oCAGE,QAAA,SAAI,WAAA,UAAA,GADjB,mBASQ,SAAA;;IAPN,OAAM;IACN,UAAA;IACA,gBAAe;IACd,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,QAAK;OACb,mBAEiB,UAAA;IADd,KAAK,QAAA;IACL,MAAM,QAAA;kDAiBX,mBAKmB,UAAA;;IAHjB,OAAM;IACN,gBAAe;IACd,SAAS,MAAA,QAAQ,KAAA,IAAS;IAC1B,KAAK,QAAA;kDAEV,YAEmB,0BAAA,EAAA,KAAA,EAAA,GAAA;2BADkD,CAAA,gBAAA,gBAAhE,MAAA,SAAA,CAAS,CAAA,kDAAA,CAAA,GAAA,CAAA,CAAA,CAAA"}
@@ -1,5 +1,6 @@
1
1
  type __VLS_Props = {
2
2
  reader: ReadableStreamDefaultReader<Uint8Array>;
3
+ contentType?: string;
3
4
  };
4
5
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
6
  declare const _default: typeof __VLS_export;
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyStreaming.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyStreaming.vue"],"names":[],"mappings":"AAkKA,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;CAChD,CAAC;AAwPF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"ResponseBodyStreaming.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyStreaming.vue"],"names":[],"mappings":"AAiNA,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAC;AAgVF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyStreaming.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyStreaming.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarLoading, useLoadingState } from '@scalar/components/loading'\nimport { nextTick, onBeforeUnmount, ref, watch } from 'vue'\n\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst { reader } = defineProps<{\n reader: ReadableStreamDefaultReader<Uint8Array>\n}>()\n\nconst loader = useLoadingState()\n\nconst textContent = ref('')\nconst errorRef = ref<Error | null>(null)\nconst contentContainer = ref<HTMLElement | null>(null)\n\n/** Track the current reader to prevent race conditions when reader changes */\nconst currentReader = ref<ReadableStreamDefaultReader<Uint8Array> | null>(null)\n\n/** Current decoder instance - reset for each new stream to prevent buffer corruption */\nconst decoder = ref<TextDecoder | null>(null)\n\n/**\n * Scrolls the content container to the bottom\n */\nconst scrollToBottom = () => {\n if (contentContainer.value) {\n contentContainer.value.scrollTop = contentContainer.value.scrollHeight\n }\n}\n\n// Watch for changes in textContent and scroll to bottom\nwatch(textContent, async () => {\n // Use nextTick to ensure the DOM has updated\n await nextTick(scrollToBottom)\n})\n\n/**\n * Reads the stream and appends the content\n */\nasync function readStream(\n streamReader: ReadableStreamDefaultReader<Uint8Array>,\n) {\n try {\n while (loader.isLoading && currentReader.value === streamReader) {\n const { done, value } = await streamReader.read()\n\n // Stop if this reader is no longer the current one\n if (currentReader.value !== streamReader) {\n break\n }\n\n if (done) {\n void loader.clear()\n break\n }\n\n // Decode the Uint8Array to string and append to content\n if (value && decoder.value) {\n textContent.value += decoder.value.decode(value, { stream: true })\n }\n }\n } catch (error) {\n // Only handle the error if this is still the current reader\n if (currentReader.value === streamReader) {\n console.error('Error reading stream:', error)\n void loader.clear()\n errorRef.value = error as Error\n }\n } finally {\n // Only finalize decoding if this is still the current reader\n if (currentReader.value === streamReader && decoder.value) {\n // Make sure to decode any remaining bytes\n textContent.value += decoder.value.decode()\n }\n }\n}\n\nconst startStreaming = () => {\n // Cancel the old reader if it exists\n if (currentReader.value) {\n currentReader.value.cancel()\n }\n\n // Set the new reader as current\n currentReader.value = reader\n\n // Reset state and start new stream\n // Create a new decoder instance to prevent buffer corruption from previous streams\n decoder.value = new TextDecoder()\n loader.start()\n textContent.value = ''\n errorRef.value = null\n void readStream(reader)\n}\n\nconst stopStreaming = () => {\n if (currentReader.value) {\n currentReader.value.cancel()\n currentReader.value = null\n }\n void loader.clear()\n}\n\n// Start streaming when the reader changes\nwatch(() => reader, startStreaming, { immediate: true })\n\nonBeforeUnmount(stopStreaming)\n</script>\n\n<template>\n <CollapsibleSection class=\"max-h-content overflow-y-hidden\">\n <template #title>\n <div class=\"flex w-full items-center justify-between\">\n <div>Body</div>\n <div\n v-if=\"loader.isLoading\"\n class=\"mr-2 flex items-center gap-2\">\n <ScalarLoading\n :loadingState=\"loader\"\n size=\"xs\" />\n <span class=\"text-c-2\"> Listening… </span>\n </div>\n </div>\n </template>\n <template\n v-if=\"loader.isLoading\"\n #actions>\n <ScalarButton\n size=\"sm\"\n variant=\"ghost\"\n @click=\"stopStreaming\">\n Cancel\n </ScalarButton>\n </template>\n\n <div\n ref=\"contentContainer\"\n class=\"text-xxs font-code h-full overflow-auto leading-6 whitespace-pre-wrap\">\n <template v-if=\"errorRef\">\n <div class=\"text-red bg-b-danger sticky top-0 border-b p-2\">\n {{ errorRef.message }}\n </div>\n </template>\n <template v-if=\"textContent\">\n <div class=\"p-2\">\n {{ textContent }}\n </div>\n </template>\n </div>\n </CollapsibleSection>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ResponseBodyStreaming.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyStreaming.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarLoading, useLoadingState } from '@scalar/components/loading'\nimport { formatBytes } from '@scalar/helpers/formatters/format-bytes'\nimport { getUtf8ByteLength } from '@scalar/helpers/string/get-utf8-byte-length'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { nextTick, onBeforeUnmount, ref, watch } from 'vue'\n\nimport { CollapsibleSection } from '@/v2/components/layout'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport { createResponseStreamParser } from '../helpers/response-stream'\n\nconst { reader, contentType = 'text/event-stream' } = defineProps<{\n reader: ReadableStreamDefaultReader<Uint8Array>\n contentType?: string\n}>()\n\nconst { translate } = useLocalization()\n\nconst loader = useLoadingState()\nconst textContent = ref('')\nconst receivedBytes = ref(0)\nconst { copyToClipboard } = useClipboard()\nlet downloadUrl: string | undefined\n\nconst clearDownload = (): void => {\n if (downloadUrl) {\n URL.revokeObjectURL(downloadUrl)\n downloadUrl = undefined\n }\n}\n\n/** Export only the bounded displayed transcript, without retaining another raw body. */\nconst downloadText = (): void => {\n clearDownload()\n downloadUrl = URL.createObjectURL(\n new Blob([textContent.value], { type: 'text/plain;charset=utf-8' }),\n )\n const link = document.createElement('a')\n link.href = downloadUrl\n link.download = 'response-stream.txt'\n link.click()\n}\nconst errorRef = ref<Error | null>(null)\nconst contentContainer = ref<HTMLElement | null>(null)\nlet currentReader: ReadableStreamDefaultReader<Uint8Array> | null = null\n\n/** Bound the text retained by a connection that can stay open indefinitely. */\nconst MAX_DISPLAY_SIZE = 16 * 1024 * 1024\n\nwatch(textContent, async () => {\n await nextTick()\n if (contentContainer.value) {\n contentContainer.value.scrollTop = contentContainer.value.scrollHeight\n }\n})\n\nconst cancelReader = (\n streamReader: ReadableStreamDefaultReader<Uint8Array>,\n): void => {\n void Promise.resolve(streamReader.cancel()).catch(() => {\n // A failed or disconnected stream can already be closed when the user cancels.\n })\n}\n\nconst readStream = async (\n streamReader: ReadableStreamDefaultReader<Uint8Array>,\n): Promise<void> => {\n try {\n let displayedBytes = 0\n const parser = createResponseStreamParser(contentType, (text) => {\n displayedBytes += getUtf8ByteLength(text)\n if (displayedBytes > MAX_DISPLAY_SIZE) {\n throw new Error(\n 'Stream display reached its 16 MiB limit. Cancelled further reading.',\n )\n }\n textContent.value += text\n })\n while (currentReader === streamReader) {\n const { done, value } = await streamReader.read()\n if (currentReader !== streamReader) {\n return\n }\n if (done) {\n parser.finish()\n void loader.clear()\n return\n }\n receivedBytes.value += value.byteLength\n parser.push(value)\n }\n } catch (error) {\n if (currentReader === streamReader) {\n console.error('Error reading stream:', error)\n errorRef.value = error instanceof Error ? error : new Error(String(error))\n cancelReader(streamReader)\n void loader.clear()\n }\n } finally {\n streamReader.releaseLock()\n }\n}\n\nconst stopStreaming = (): void => {\n const previous = currentReader\n currentReader = null\n if (previous) {\n cancelReader(previous)\n }\n void loader.clear()\n}\n\nconst startStreaming = (): void => {\n stopStreaming()\n currentReader = reader\n loader.start()\n clearDownload()\n receivedBytes.value = 0\n textContent.value = ''\n errorRef.value = null\n void readStream(reader)\n}\n\nwatch(() => reader, startStreaming, { immediate: true })\nonBeforeUnmount(() => {\n stopStreaming()\n clearDownload()\n})\n</script>\n\n<template>\n <CollapsibleSection class=\"max-h-content overflow-y-hidden\">\n <template #title>\n <div class=\"flex w-full items-center justify-between\">\n <div>\n {{ translate('apiClient.responseBodyStreaming.body') }}\n <span class=\"text-c-2 ml-2 text-xs\">\n {{ formatBytes(receivedBytes) }} received\n </span>\n </div>\n <div\n v-if=\"loader.isLoading\"\n class=\"mr-2 flex items-center gap-2\">\n <ScalarLoading\n :loadingState=\"loader\"\n size=\"xs\" />\n <span class=\"text-c-2\">{{\n translate('apiClient.responseBodyStreaming.listening')\n }}</span>\n </div>\n </div>\n </template>\n <template #actions>\n <ScalarButton\n v-if=\"loader.isLoading\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"stopStreaming\">\n {{ translate('apiClient.responseBodyStreaming.cancel') }}\n </ScalarButton>\n <ScalarButton\n v-if=\"textContent\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"copyToClipboard(textContent)\">\n Copy text\n </ScalarButton>\n <ScalarButton\n v-if=\"textContent\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"downloadText\">\n Download text\n </ScalarButton>\n </template>\n\n <div\n ref=\"contentContainer\"\n class=\"text-xxs font-code h-full overflow-auto leading-6 whitespace-pre-wrap\">\n <template v-if=\"errorRef\">\n <div class=\"text-red bg-b-danger sticky top-0 border-b p-2\">\n {{ errorRef.message }}\n </div>\n </template>\n <template v-if=\"textContent\">\n <div class=\"p-2\">\n {{ textContent }}\n </div>\n </template>\n </div>\n </CollapsibleSection>\n</template>\n"],"mappings":""}
@@ -1,108 +1,161 @@
1
+ import { useLocalization } from "../../../features/localization/index.js";
2
+ import { createResponseStreamParser } from "../helpers/response-stream.js";
1
3
  import CollapsibleSection_default from "../../../components/layout/CollapsibleSection.vue.js";
2
- import { createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, nextTick, onBeforeUnmount, openBlock, ref, toDisplayString, unref, watch, withCtx } from "vue";
4
+ import { createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, onBeforeUnmount, openBlock, ref, toDisplayString, unref, watch, withCtx } from "vue";
3
5
  import { ScalarButton } from "@scalar/components/button";
6
+ import { getUtf8ByteLength } from "@scalar/helpers/string/get-utf8-byte-length";
7
+ import { useClipboard } from "@scalar/use-hooks/useClipboard";
4
8
  import { ScalarLoading, useLoadingState } from "@scalar/components/loading";
9
+ import { formatBytes } from "@scalar/helpers/formatters/format-bytes";
5
10
  //#region src/v2/blocks/response-block/components/ResponseBodyStreaming.vue?vue&type=script&setup=true&lang.ts
6
11
  var _hoisted_1 = { class: "flex w-full items-center justify-between" };
7
- var _hoisted_2 = {
12
+ var _hoisted_2 = { class: "text-c-2 ml-2 text-xs" };
13
+ var _hoisted_3 = {
8
14
  key: 0,
9
15
  class: "mr-2 flex items-center gap-2"
10
16
  };
11
- var _hoisted_3 = {
17
+ var _hoisted_4 = { class: "text-c-2" };
18
+ var _hoisted_5 = {
12
19
  key: 0,
13
20
  class: "text-red bg-b-danger sticky top-0 border-b p-2"
14
21
  };
15
- var _hoisted_4 = {
22
+ var _hoisted_6 = {
16
23
  key: 1,
17
24
  class: "p-2"
18
25
  };
26
+ var MAX_DISPLAY_SIZE = 16 * 1024 * 1024;
19
27
  var ResponseBodyStreaming_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
20
28
  __name: "ResponseBodyStreaming",
21
- props: { reader: {} },
29
+ props: {
30
+ reader: {},
31
+ contentType: { default: "text/event-stream" }
32
+ },
22
33
  setup(__props) {
34
+ const { translate } = useLocalization();
23
35
  const loader = useLoadingState();
24
36
  const textContent = ref("");
37
+ const receivedBytes = ref(0);
38
+ const { copyToClipboard } = useClipboard();
39
+ let downloadUrl;
40
+ const clearDownload = () => {
41
+ if (downloadUrl) {
42
+ URL.revokeObjectURL(downloadUrl);
43
+ downloadUrl = void 0;
44
+ }
45
+ };
46
+ /** Export only the bounded displayed transcript, without retaining another raw body. */
47
+ const downloadText = () => {
48
+ clearDownload();
49
+ downloadUrl = URL.createObjectURL(new Blob([textContent.value], { type: "text/plain;charset=utf-8" }));
50
+ const link = document.createElement("a");
51
+ link.href = downloadUrl;
52
+ link.download = "response-stream.txt";
53
+ link.click();
54
+ };
25
55
  const errorRef = ref(null);
26
56
  const contentContainer = ref(null);
27
- /** Track the current reader to prevent race conditions when reader changes */
28
- const currentReader = ref(null);
29
- /** Current decoder instance - reset for each new stream to prevent buffer corruption */
30
- const decoder = ref(null);
31
- /**
32
- * Scrolls the content container to the bottom
33
- */
34
- const scrollToBottom = () => {
35
- if (contentContainer.value) contentContainer.value.scrollTop = contentContainer.value.scrollHeight;
36
- };
57
+ let currentReader = null;
58
+ /** Bound the text retained by a connection that can stay open indefinitely. */
37
59
  watch(textContent, async () => {
38
- await nextTick(scrollToBottom);
60
+ await nextTick();
61
+ if (contentContainer.value) contentContainer.value.scrollTop = contentContainer.value.scrollHeight;
39
62
  });
40
- /**
41
- * Reads the stream and appends the content
42
- */
43
- async function readStream(streamReader) {
63
+ const cancelReader = (streamReader) => {
64
+ Promise.resolve(streamReader.cancel()).catch(() => {});
65
+ };
66
+ const readStream = async (streamReader) => {
44
67
  try {
45
- while (loader.isLoading && currentReader.value === streamReader) {
68
+ let displayedBytes = 0;
69
+ const parser = createResponseStreamParser(__props.contentType, (text) => {
70
+ displayedBytes += getUtf8ByteLength(text);
71
+ if (displayedBytes > MAX_DISPLAY_SIZE) throw new Error("Stream display reached its 16 MiB limit. Cancelled further reading.");
72
+ textContent.value += text;
73
+ });
74
+ while (currentReader === streamReader) {
46
75
  const { done, value } = await streamReader.read();
47
- if (currentReader.value !== streamReader) break;
76
+ if (currentReader !== streamReader) return;
48
77
  if (done) {
78
+ parser.finish();
49
79
  loader.clear();
50
- break;
80
+ return;
51
81
  }
52
- if (value && decoder.value) textContent.value += decoder.value.decode(value, { stream: true });
82
+ receivedBytes.value += value.byteLength;
83
+ parser.push(value);
53
84
  }
54
85
  } catch (error) {
55
- if (currentReader.value === streamReader) {
86
+ if (currentReader === streamReader) {
56
87
  console.error("Error reading stream:", error);
88
+ errorRef.value = error instanceof Error ? error : new Error(String(error));
89
+ cancelReader(streamReader);
57
90
  loader.clear();
58
- errorRef.value = error;
59
91
  }
60
92
  } finally {
61
- if (currentReader.value === streamReader && decoder.value) textContent.value += decoder.value.decode();
93
+ streamReader.releaseLock();
62
94
  }
63
- }
95
+ };
96
+ const stopStreaming = () => {
97
+ const previous = currentReader;
98
+ currentReader = null;
99
+ if (previous) cancelReader(previous);
100
+ loader.clear();
101
+ };
64
102
  const startStreaming = () => {
65
- if (currentReader.value) currentReader.value.cancel();
66
- currentReader.value = __props.reader;
67
- decoder.value = new TextDecoder();
103
+ stopStreaming();
104
+ currentReader = __props.reader;
68
105
  loader.start();
106
+ clearDownload();
107
+ receivedBytes.value = 0;
69
108
  textContent.value = "";
70
109
  errorRef.value = null;
71
110
  readStream(__props.reader);
72
111
  };
73
- const stopStreaming = () => {
74
- if (currentReader.value) {
75
- currentReader.value.cancel();
76
- currentReader.value = null;
77
- }
78
- loader.clear();
79
- };
80
112
  watch(() => __props.reader, startStreaming, { immediate: true });
81
- onBeforeUnmount(stopStreaming);
113
+ onBeforeUnmount(() => {
114
+ stopStreaming();
115
+ clearDownload();
116
+ });
82
117
  return (_ctx, _cache) => {
83
- return openBlock(), createBlock(unref(CollapsibleSection_default), { class: "max-h-content overflow-y-hidden" }, createSlots({
84
- title: withCtx(() => [createElementVNode("div", _hoisted_1, [_cache[1] || (_cache[1] = createElementVNode("div", null, "Body", -1)), unref(loader).isLoading ? (openBlock(), createElementBlock("div", _hoisted_2, [createVNode(unref(ScalarLoading), {
118
+ return openBlock(), createBlock(unref(CollapsibleSection_default), { class: "max-h-content overflow-y-hidden" }, {
119
+ title: withCtx(() => [createElementVNode("div", _hoisted_1, [createElementVNode("div", null, [createTextVNode(toDisplayString(unref(translate)("apiClient.responseBodyStreaming.body")) + " ", 1), createElementVNode("span", _hoisted_2, toDisplayString(unref(formatBytes)(receivedBytes.value)) + " received ", 1)]), unref(loader).isLoading ? (openBlock(), createElementBlock("div", _hoisted_3, [createVNode(unref(ScalarLoading), {
85
120
  loadingState: unref(loader),
86
121
  size: "xs"
87
- }, null, 8, ["loadingState"]), _cache[0] || (_cache[0] = createElementVNode("span", { class: "text-c-2" }, " Listening… ", -1))])) : createCommentVNode("", true)])]),
122
+ }, null, 8, ["loadingState"]), createElementVNode("span", _hoisted_4, toDisplayString(unref(translate)("apiClient.responseBodyStreaming.listening")), 1)])) : createCommentVNode("", true)])]),
123
+ actions: withCtx(() => [
124
+ unref(loader).isLoading ? (openBlock(), createBlock(unref(ScalarButton), {
125
+ key: 0,
126
+ size: "sm",
127
+ variant: "ghost",
128
+ onClick: stopStreaming
129
+ }, {
130
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.responseBodyStreaming.cancel")), 1)]),
131
+ _: 1
132
+ })) : createCommentVNode("", true),
133
+ textContent.value ? (openBlock(), createBlock(unref(ScalarButton), {
134
+ key: 1,
135
+ size: "sm",
136
+ variant: "ghost",
137
+ onClick: _cache[0] || (_cache[0] = ($event) => unref(copyToClipboard)(textContent.value))
138
+ }, {
139
+ default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode(" Copy text ", -1)])]),
140
+ _: 1
141
+ })) : createCommentVNode("", true),
142
+ textContent.value ? (openBlock(), createBlock(unref(ScalarButton), {
143
+ key: 2,
144
+ size: "sm",
145
+ variant: "ghost",
146
+ onClick: downloadText
147
+ }, {
148
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode(" Download text ", -1)])]),
149
+ _: 1
150
+ })) : createCommentVNode("", true)
151
+ ]),
88
152
  default: withCtx(() => [createElementVNode("div", {
89
153
  ref_key: "contentContainer",
90
154
  ref: contentContainer,
91
155
  class: "text-xxs font-code h-full overflow-auto leading-6 whitespace-pre-wrap"
92
- }, [errorRef.value ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(errorRef.value.message), 1)) : createCommentVNode("", true), textContent.value ? (openBlock(), createElementBlock("div", _hoisted_4, toDisplayString(textContent.value), 1)) : createCommentVNode("", true)], 512)]),
93
- _: 2
94
- }, [unref(loader).isLoading ? {
95
- name: "actions",
96
- fn: withCtx(() => [createVNode(unref(ScalarButton), {
97
- size: "sm",
98
- variant: "ghost",
99
- onClick: stopStreaming
100
- }, {
101
- default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode(" Cancel ", -1)])]),
102
- _: 1
103
- })]),
104
- key: "0"
105
- } : void 0]), 1024);
156
+ }, [errorRef.value ? (openBlock(), createElementBlock("div", _hoisted_5, toDisplayString(errorRef.value.message), 1)) : createCommentVNode("", true), textContent.value ? (openBlock(), createElementBlock("div", _hoisted_6, toDisplayString(textContent.value), 1)) : createCommentVNode("", true)], 512)]),
157
+ _: 1
158
+ });
106
159
  };
107
160
  }
108
161
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyStreaming.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyStreaming.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarLoading, useLoadingState } from '@scalar/components/loading'\nimport { nextTick, onBeforeUnmount, ref, watch } from 'vue'\n\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst { reader } = defineProps<{\n reader: ReadableStreamDefaultReader<Uint8Array>\n}>()\n\nconst loader = useLoadingState()\n\nconst textContent = ref('')\nconst errorRef = ref<Error | null>(null)\nconst contentContainer = ref<HTMLElement | null>(null)\n\n/** Track the current reader to prevent race conditions when reader changes */\nconst currentReader = ref<ReadableStreamDefaultReader<Uint8Array> | null>(null)\n\n/** Current decoder instance - reset for each new stream to prevent buffer corruption */\nconst decoder = ref<TextDecoder | null>(null)\n\n/**\n * Scrolls the content container to the bottom\n */\nconst scrollToBottom = () => {\n if (contentContainer.value) {\n contentContainer.value.scrollTop = contentContainer.value.scrollHeight\n }\n}\n\n// Watch for changes in textContent and scroll to bottom\nwatch(textContent, async () => {\n // Use nextTick to ensure the DOM has updated\n await nextTick(scrollToBottom)\n})\n\n/**\n * Reads the stream and appends the content\n */\nasync function readStream(\n streamReader: ReadableStreamDefaultReader<Uint8Array>,\n) {\n try {\n while (loader.isLoading && currentReader.value === streamReader) {\n const { done, value } = await streamReader.read()\n\n // Stop if this reader is no longer the current one\n if (currentReader.value !== streamReader) {\n break\n }\n\n if (done) {\n void loader.clear()\n break\n }\n\n // Decode the Uint8Array to string and append to content\n if (value && decoder.value) {\n textContent.value += decoder.value.decode(value, { stream: true })\n }\n }\n } catch (error) {\n // Only handle the error if this is still the current reader\n if (currentReader.value === streamReader) {\n console.error('Error reading stream:', error)\n void loader.clear()\n errorRef.value = error as Error\n }\n } finally {\n // Only finalize decoding if this is still the current reader\n if (currentReader.value === streamReader && decoder.value) {\n // Make sure to decode any remaining bytes\n textContent.value += decoder.value.decode()\n }\n }\n}\n\nconst startStreaming = () => {\n // Cancel the old reader if it exists\n if (currentReader.value) {\n currentReader.value.cancel()\n }\n\n // Set the new reader as current\n currentReader.value = reader\n\n // Reset state and start new stream\n // Create a new decoder instance to prevent buffer corruption from previous streams\n decoder.value = new TextDecoder()\n loader.start()\n textContent.value = ''\n errorRef.value = null\n void readStream(reader)\n}\n\nconst stopStreaming = () => {\n if (currentReader.value) {\n currentReader.value.cancel()\n currentReader.value = null\n }\n void loader.clear()\n}\n\n// Start streaming when the reader changes\nwatch(() => reader, startStreaming, { immediate: true })\n\nonBeforeUnmount(stopStreaming)\n</script>\n\n<template>\n <CollapsibleSection class=\"max-h-content overflow-y-hidden\">\n <template #title>\n <div class=\"flex w-full items-center justify-between\">\n <div>Body</div>\n <div\n v-if=\"loader.isLoading\"\n class=\"mr-2 flex items-center gap-2\">\n <ScalarLoading\n :loadingState=\"loader\"\n size=\"xs\" />\n <span class=\"text-c-2\"> Listening… </span>\n </div>\n </div>\n </template>\n <template\n v-if=\"loader.isLoading\"\n #actions>\n <ScalarButton\n size=\"sm\"\n variant=\"ghost\"\n @click=\"stopStreaming\">\n Cancel\n </ScalarButton>\n </template>\n\n <div\n ref=\"contentContainer\"\n class=\"text-xxs font-code h-full overflow-auto leading-6 whitespace-pre-wrap\">\n <template v-if=\"errorRef\">\n <div class=\"text-red bg-b-danger sticky top-0 border-b p-2\">\n {{ errorRef.message }}\n </div>\n </template>\n <template v-if=\"textContent\">\n <div class=\"p-2\">\n {{ textContent }}\n </div>\n </template>\n </div>\n </CollapsibleSection>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAWA,MAAM,SAAS,gBAAgB;EAE/B,MAAM,cAAc,IAAI,EAAE;EAC1B,MAAM,WAAW,IAAkB,IAAI;EACvC,MAAM,mBAAmB,IAAwB,IAAI;;EAGrD,MAAM,gBAAgB,IAAoD,IAAI;;EAG9E,MAAM,UAAU,IAAwB,IAAI;;;;EAK5C,MAAM,uBAAuB;GAC3B,IAAI,iBAAiB,OACnB,iBAAiB,MAAM,YAAY,iBAAiB,MAAM;EAE9D;EAGA,MAAM,aAAa,YAAY;GAE7B,MAAM,SAAS,cAAc;EAC/B,CAAC;;;;EAKD,eAAe,WACb,cACA;GACA,IAAI;IACF,OAAO,OAAO,aAAa,cAAc,UAAU,cAAc;KAC/D,MAAM,EAAE,MAAM,UAAU,MAAM,aAAa,KAAK;KAGhD,IAAI,cAAc,UAAU,cAC1B;KAGF,IAAI,MAAM;MACR,OAAY,MAAM;MAClB;KACF;KAGA,IAAI,SAAS,QAAQ,OACnB,YAAY,SAAS,QAAQ,MAAM,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;IAErE;GACF,SAAS,OAAO;IAEd,IAAI,cAAc,UAAU,cAAc;KACxC,QAAQ,MAAM,yBAAyB,KAAK;KAC5C,OAAY,MAAM;KAClB,SAAS,QAAQ;IACnB;GACF,UAAU;IAER,IAAI,cAAc,UAAU,gBAAgB,QAAQ,OAElD,YAAY,SAAS,QAAQ,MAAM,OAAO;GAE9C;EACF;EAEA,MAAM,uBAAuB;GAE3B,IAAI,cAAc,OAChB,cAAc,MAAM,OAAO;GAI7B,cAAc,QAAQ,QAAA;GAItB,QAAQ,QAAQ,IAAI,YAAY;GAChC,OAAO,MAAM;GACb,YAAY,QAAQ;GACpB,SAAS,QAAQ;GACjB,WAAgB,QAAA,MAAM;EACxB;EAEA,MAAM,sBAAsB;GAC1B,IAAI,cAAc,OAAO;IACvB,cAAc,MAAM,OAAO;IAC3B,cAAc,QAAQ;GACxB;GACA,OAAY,MAAM;EACpB;EAGA,YAAY,QAAA,QAAQ,gBAAgB,EAAE,WAAW,KAAK,CAAC;EAEvD,gBAAgB,aAAa;;uBAI3B,YAuCqB,MAAA,0BAAA,GAAA,EAvCD,OAAM,kCAAiC,GAAA,YAAA;IAC9C,OAAK,cAWR,CAVN,mBAUM,OAVN,YAUM,CAAA,OAAA,OAAA,OAAA,KATJ,mBAAe,OAAA,MAAV,QAAI,EAAA,IAED,MAAA,MAAA,CAAM,CAAC,aAAA,UAAA,GADf,mBAOM,OAPN,YAOM,CAJJ,YAEc,MAAA,aAAA,GAAA;KADX,cAAc,MAAA,MAAA;KACf,MAAK;6DACP,mBAA0C,QAAA,EAApC,OAAM,WAAU,GAAC,gBAAY,EAAA,EAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,CAAA,CAAA;2BA4BnC,CAbN,mBAaM,OAAA;cAZA;KAAJ,KAAI;KACJ,OAAM;QACU,SAAA,SAAA,UAAA,GACd,mBAEM,OAFN,YAEM,gBADD,SAAA,MAAS,OAAO,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,GAGP,YAAA,SAAA,UAAA,GACd,mBAEM,OAFN,YAEM,gBADD,YAAA,KAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,GAAA,CAAA,CAAA;;OApBZ,MAAA,MAAA,CAAM,CAAC,YAAA;UACZ;sBAMc,CALf,YAKe,MAAA,YAAA,GAAA;KAJb,MAAK;KACL,SAAQ;KACP,SAAO;;4BAEV,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAFyB,YAEzB,EAAA,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"ResponseBodyStreaming.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyStreaming.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarLoading, useLoadingState } from '@scalar/components/loading'\nimport { formatBytes } from '@scalar/helpers/formatters/format-bytes'\nimport { getUtf8ByteLength } from '@scalar/helpers/string/get-utf8-byte-length'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { nextTick, onBeforeUnmount, ref, watch } from 'vue'\n\nimport { CollapsibleSection } from '@/v2/components/layout'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport { createResponseStreamParser } from '../helpers/response-stream'\n\nconst { reader, contentType = 'text/event-stream' } = defineProps<{\n reader: ReadableStreamDefaultReader<Uint8Array>\n contentType?: string\n}>()\n\nconst { translate } = useLocalization()\n\nconst loader = useLoadingState()\nconst textContent = ref('')\nconst receivedBytes = ref(0)\nconst { copyToClipboard } = useClipboard()\nlet downloadUrl: string | undefined\n\nconst clearDownload = (): void => {\n if (downloadUrl) {\n URL.revokeObjectURL(downloadUrl)\n downloadUrl = undefined\n }\n}\n\n/** Export only the bounded displayed transcript, without retaining another raw body. */\nconst downloadText = (): void => {\n clearDownload()\n downloadUrl = URL.createObjectURL(\n new Blob([textContent.value], { type: 'text/plain;charset=utf-8' }),\n )\n const link = document.createElement('a')\n link.href = downloadUrl\n link.download = 'response-stream.txt'\n link.click()\n}\nconst errorRef = ref<Error | null>(null)\nconst contentContainer = ref<HTMLElement | null>(null)\nlet currentReader: ReadableStreamDefaultReader<Uint8Array> | null = null\n\n/** Bound the text retained by a connection that can stay open indefinitely. */\nconst MAX_DISPLAY_SIZE = 16 * 1024 * 1024\n\nwatch(textContent, async () => {\n await nextTick()\n if (contentContainer.value) {\n contentContainer.value.scrollTop = contentContainer.value.scrollHeight\n }\n})\n\nconst cancelReader = (\n streamReader: ReadableStreamDefaultReader<Uint8Array>,\n): void => {\n void Promise.resolve(streamReader.cancel()).catch(() => {\n // A failed or disconnected stream can already be closed when the user cancels.\n })\n}\n\nconst readStream = async (\n streamReader: ReadableStreamDefaultReader<Uint8Array>,\n): Promise<void> => {\n try {\n let displayedBytes = 0\n const parser = createResponseStreamParser(contentType, (text) => {\n displayedBytes += getUtf8ByteLength(text)\n if (displayedBytes > MAX_DISPLAY_SIZE) {\n throw new Error(\n 'Stream display reached its 16 MiB limit. Cancelled further reading.',\n )\n }\n textContent.value += text\n })\n while (currentReader === streamReader) {\n const { done, value } = await streamReader.read()\n if (currentReader !== streamReader) {\n return\n }\n if (done) {\n parser.finish()\n void loader.clear()\n return\n }\n receivedBytes.value += value.byteLength\n parser.push(value)\n }\n } catch (error) {\n if (currentReader === streamReader) {\n console.error('Error reading stream:', error)\n errorRef.value = error instanceof Error ? error : new Error(String(error))\n cancelReader(streamReader)\n void loader.clear()\n }\n } finally {\n streamReader.releaseLock()\n }\n}\n\nconst stopStreaming = (): void => {\n const previous = currentReader\n currentReader = null\n if (previous) {\n cancelReader(previous)\n }\n void loader.clear()\n}\n\nconst startStreaming = (): void => {\n stopStreaming()\n currentReader = reader\n loader.start()\n clearDownload()\n receivedBytes.value = 0\n textContent.value = ''\n errorRef.value = null\n void readStream(reader)\n}\n\nwatch(() => reader, startStreaming, { immediate: true })\nonBeforeUnmount(() => {\n stopStreaming()\n clearDownload()\n})\n</script>\n\n<template>\n <CollapsibleSection class=\"max-h-content overflow-y-hidden\">\n <template #title>\n <div class=\"flex w-full items-center justify-between\">\n <div>\n {{ translate('apiClient.responseBodyStreaming.body') }}\n <span class=\"text-c-2 ml-2 text-xs\">\n {{ formatBytes(receivedBytes) }} received\n </span>\n </div>\n <div\n v-if=\"loader.isLoading\"\n class=\"mr-2 flex items-center gap-2\">\n <ScalarLoading\n :loadingState=\"loader\"\n size=\"xs\" />\n <span class=\"text-c-2\">{{\n translate('apiClient.responseBodyStreaming.listening')\n }}</span>\n </div>\n </div>\n </template>\n <template #actions>\n <ScalarButton\n v-if=\"loader.isLoading\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"stopStreaming\">\n {{ translate('apiClient.responseBodyStreaming.cancel') }}\n </ScalarButton>\n <ScalarButton\n v-if=\"textContent\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"copyToClipboard(textContent)\">\n Copy text\n </ScalarButton>\n <ScalarButton\n v-if=\"textContent\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"downloadText\">\n Download text\n </ScalarButton>\n </template>\n\n <div\n ref=\"contentContainer\"\n class=\"text-xxs font-code h-full overflow-auto leading-6 whitespace-pre-wrap\">\n <template v-if=\"errorRef\">\n <div class=\"text-red bg-b-danger sticky top-0 border-b p-2\">\n {{ errorRef.message }}\n </div>\n </template>\n <template v-if=\"textContent\">\n <div class=\"p-2\">\n {{ textContent }}\n </div>\n </template>\n </div>\n </CollapsibleSection>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,IAAM,mBAAmB,KAAK,OAAO;;;;;;;;EA/BrC,MAAM,EAAE,cAAc,gBAAgB;EAEtC,MAAM,SAAS,gBAAgB;EAC/B,MAAM,cAAc,IAAI,EAAE;EAC1B,MAAM,gBAAgB,IAAI,CAAC;EAC3B,MAAM,EAAE,oBAAoB,aAAa;EACzC,IAAI;EAEJ,MAAM,sBAA4B;GAChC,IAAI,aAAa;IACf,IAAI,gBAAgB,WAAW;IAC/B,cAAc,KAAA;GAChB;EACF;;EAGA,MAAM,qBAA2B;GAC/B,cAAc;GACd,cAAc,IAAI,gBAChB,IAAI,KAAK,CAAC,YAAY,KAAK,GAAG,EAAE,MAAM,2BAA2B,CAAC,CACpE;GACA,MAAM,OAAO,SAAS,cAAc,GAAG;GACvC,KAAK,OAAO;GACZ,KAAK,WAAW;GAChB,KAAK,MAAM;EACb;EACA,MAAM,WAAW,IAAkB,IAAI;EACvC,MAAM,mBAAmB,IAAwB,IAAI;EACrD,IAAI,gBAAgE;;EAKpE,MAAM,aAAa,YAAY;GAC7B,MAAM,SAAS;GACf,IAAI,iBAAiB,OACnB,iBAAiB,MAAM,YAAY,iBAAiB,MAAM;EAE9D,CAAC;EAED,MAAM,gBACJ,iBACS;GACT,QAAa,QAAQ,aAAa,OAAO,CAAC,CAAC,CAAC,YAAY,CAExD,CAAC;EACH;EAEA,MAAM,aAAa,OACjB,iBACkB;GAClB,IAAI;IACF,IAAI,iBAAiB;IACrB,MAAM,SAAS,2BAA2B,QAAA,cAAc,SAAS;KAC/D,kBAAkB,kBAAkB,IAAI;KACxC,IAAI,iBAAiB,kBACnB,MAAM,IAAI,MACR,qEACF;KAEF,YAAY,SAAS;IACvB,CAAC;IACD,OAAO,kBAAkB,cAAc;KACrC,MAAM,EAAE,MAAM,UAAU,MAAM,aAAa,KAAK;KAChD,IAAI,kBAAkB,cACpB;KAEF,IAAI,MAAM;MACR,OAAO,OAAO;MACd,OAAY,MAAM;MAClB;KACF;KACA,cAAc,SAAS,MAAM;KAC7B,OAAO,KAAK,KAAK;IACnB;GACF,SAAS,OAAO;IACd,IAAI,kBAAkB,cAAc;KAClC,QAAQ,MAAM,yBAAyB,KAAK;KAC5C,SAAS,QAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;KACzE,aAAa,YAAY;KACzB,OAAY,MAAM;IACpB;GACF,UAAU;IACR,aAAa,YAAY;GAC3B;EACF;EAEA,MAAM,sBAA4B;GAChC,MAAM,WAAW;GACjB,gBAAgB;GAChB,IAAI,UACF,aAAa,QAAQ;GAEvB,OAAY,MAAM;EACpB;EAEA,MAAM,uBAA6B;GACjC,cAAc;GACd,gBAAgB,QAAA;GAChB,OAAO,MAAM;GACb,cAAc;GACd,cAAc,QAAQ;GACtB,YAAY,QAAQ;GACpB,SAAS,QAAQ;GACjB,WAAgB,QAAA,MAAM;EACxB;EAEA,YAAY,QAAA,QAAQ,gBAAgB,EAAE,WAAW,KAAK,CAAC;EACvD,sBAAsB;GACpB,cAAc;GACd,cAAc;EAChB,CAAC;;uBAIC,YA2DqB,MAAA,0BAAA,GAAA,EA3DD,OAAM,kCAAiC,GAAA;IAC9C,OAAK,cAkBR,CAjBN,mBAiBM,OAjBN,YAiBM,CAhBJ,mBAKM,OAAA,MAAA,CAAA,gBAAA,gBAJD,MAAA,SAAA,CAAS,CAAA,sCAAA,CAAA,IAA2C,KACvD,CAAA,GAAA,mBAEO,QAFP,YAEO,gBADF,MAAA,WAAA,CAAW,CAAC,cAAA,KAAa,CAAA,IAAI,cAClC,CAAA,CAAA,CAAA,GAGM,MAAA,MAAA,CAAM,CAAC,aAAA,UAAA,GADf,mBASM,OATN,YASM,CANJ,YAEc,MAAA,aAAA,GAAA;KADX,cAAc,MAAA,MAAA;KACf,MAAK;mCACP,mBAES,QAFT,YAES,gBADP,MAAA,SAAA,CAAS,CAAA,2CAAA,CAAA,GAAA,CAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,CAAA,CAAA;IAKN,SAAO,cAOD;KALP,MAAA,MAAA,CAAM,CAAC,aAAA,UAAA,GADf,YAMe,MAAA,YAAA,GAAA;;MAJb,MAAK;MACL,SAAQ;MACP,SAAO;;6BACiD,CAAA,gBAAA,gBAAtD,MAAA,SAAA,CAAS,CAAA,wCAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;KAGN,YAAA,SAAA,UAAA,GADR,YAMe,MAAA,YAAA,GAAA;;MAJb,MAAK;MACL,SAAQ;MACP,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,eAAA,CAAe,CAAC,YAAA,KAAW;;6BAErC,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAFwC,eAExC,EAAA,CAAA,EAAA,CAAA;;;KAEQ,YAAA,SAAA,UAAA,GADR,YAMe,MAAA,YAAA,GAAA;;MAJb,MAAK;MACL,SAAQ;MACP,SAAO;;6BAEV,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAFwB,mBAExB,EAAA,CAAA,EAAA,CAAA;;;;2BAgBI,CAbN,mBAaM,OAAA;cAZA;KAAJ,KAAI;KACJ,OAAM;QACU,SAAA,SAAA,UAAA,GACd,mBAEM,OAFN,YAEM,gBADD,SAAA,MAAS,OAAO,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,GAGP,YAAA,SAAA,UAAA,GACd,mBAEM,OAFN,YAEM,gBADD,YAAA,KAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,GAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyToggle.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyToggle.vue"],"names":[],"mappings":"AA8BA,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAC;AAqEF,QAAA,MAAM,YAAY;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"ResponseBodyToggle.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyToggle.vue"],"names":[],"mappings":"AAqCA,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAC;AA8EF,QAAA,MAAM,YAAY;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyToggle.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyToggle.vue"],"sourcesContent":["<script lang=\"ts\" setup>\ndefineProps<{\n modelValue: boolean\n}>()\ndefineEmits<{\n (e: 'update:modelValue', v: boolean): void\n}>()\n</script>\n<template>\n <div\n class=\"text-c-3 text-xxs -my-1 flex justify-center gap-0.5 rounded p-0.5\">\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', true)\">\n Preview\n </button>\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': !modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', false)\">\n Raw\n </button>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ResponseBodyToggle.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyToggle.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useLocalization } from '@/v2/features/localization'\n\ndefineProps<{\n modelValue: boolean\n}>()\n\ndefineEmits<{\n (e: 'update:modelValue', v: boolean): void\n}>()\n\nconst { translate } = useLocalization()\n</script>\n<template>\n <div\n class=\"text-c-3 text-xxs -my-1 flex justify-center gap-0.5 rounded p-0.5\">\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', true)\">\n {{ translate('apiClient.responseBodyToggle.preview') }}\n </button>\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': !modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', false)\">\n {{ translate('apiClient.responseBodyToggle.raw') }}\n </button>\n </div>\n</template>\n"],"mappings":""}
@@ -1,4 +1,5 @@
1
- import { createElementBlock, createElementVNode, defineComponent, normalizeClass, openBlock, withModifiers } from "vue";
1
+ import { useLocalization } from "../../../features/localization/index.js";
2
+ import { createElementBlock, createElementVNode, defineComponent, normalizeClass, openBlock, toDisplayString, unref, withModifiers } from "vue";
2
3
  //#region src/v2/blocks/response-block/components/ResponseBodyToggle.vue?vue&type=script&setup=true&lang.ts
3
4
  var _hoisted_1 = { class: "text-c-3 text-xxs -my-1 flex justify-center gap-0.5 rounded p-0.5" };
4
5
  var ResponseBodyToggle_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
@@ -6,16 +7,17 @@ var ResponseBodyToggle_vue_vue_type_script_setup_true_lang_default = /*@__PURE__
6
7
  props: { modelValue: { type: Boolean } },
7
8
  emits: ["update:modelValue"],
8
9
  setup(__props) {
10
+ const { translate } = useLocalization();
9
11
  return (_ctx, _cache) => {
10
12
  return openBlock(), createElementBlock("div", _hoisted_1, [createElementVNode("button", {
11
13
  class: normalizeClass(["hover:bg-b-3 rounded px-1", { "bg-b-3 text-c-1 cursor-default": __props.modelValue }]),
12
14
  type: "button",
13
15
  onClick: _cache[0] || (_cache[0] = withModifiers(($event) => _ctx.$emit("update:modelValue", true), ["stop"]))
14
- }, " Preview ", 2), createElementVNode("button", {
16
+ }, toDisplayString(unref(translate)("apiClient.responseBodyToggle.preview")), 3), createElementVNode("button", {
15
17
  class: normalizeClass(["hover:bg-b-3 rounded px-1", { "bg-b-3 text-c-1 cursor-default": !__props.modelValue }]),
16
18
  type: "button",
17
19
  onClick: _cache[1] || (_cache[1] = withModifiers(($event) => _ctx.$emit("update:modelValue", false), ["stop"]))
18
- }, " Raw ", 2)]);
20
+ }, toDisplayString(unref(translate)("apiClient.responseBodyToggle.raw")), 3)]);
19
21
  };
20
22
  }
21
23
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyToggle.vue.script.js","names":["$emit"],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyToggle.vue"],"sourcesContent":["<script lang=\"ts\" setup>\ndefineProps<{\n modelValue: boolean\n}>()\ndefineEmits<{\n (e: 'update:modelValue', v: boolean): void\n}>()\n</script>\n<template>\n <div\n class=\"text-c-3 text-xxs -my-1 flex justify-center gap-0.5 rounded p-0.5\">\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', true)\">\n Preview\n </button>\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': !modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', false)\">\n Raw\n </button>\n </div>\n</template>\n"],"mappings":";;;;;;;;;uBASE,mBAgBM,OAhBN,YAgBM,CAdJ,mBAMS,UAAA;IALP,OAAK,eAAA,CAAC,6BAA2B,EAAA,kCACW,QAAA,WAAU,CAAA,CAAA;IACtD,MAAK;IACJ,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAOA,KAAAA,MAAK,qBAAA,IAAA,GAAA,CAAA,MAAA,CAAA;MAA6B,aAEjD,CAAA,GACA,mBAMS,UAAA;IALP,OAAK,eAAA,CAAC,6BAA2B,EAAA,kCAAA,CACY,QAAA,WAAU,CAAA,CAAA;IACvD,MAAK;IACJ,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAOA,KAAAA,MAAK,qBAAA,KAAA,GAAA,CAAA,MAAA,CAAA;MAA8B,SAElD,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"ResponseBodyToggle.vue.script.js","names":["$emit"],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyToggle.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useLocalization } from '@/v2/features/localization'\n\ndefineProps<{\n modelValue: boolean\n}>()\n\ndefineEmits<{\n (e: 'update:modelValue', v: boolean): void\n}>()\n\nconst { translate } = useLocalization()\n</script>\n<template>\n <div\n class=\"text-c-3 text-xxs -my-1 flex justify-center gap-0.5 rounded p-0.5\">\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', true)\">\n {{ translate('apiClient.responseBodyToggle.preview') }}\n </button>\n <button\n class=\"hover:bg-b-3 rounded px-1\"\n :class=\"{ 'bg-b-3 text-c-1 cursor-default': !modelValue }\"\n type=\"button\"\n @click.stop=\"$emit('update:modelValue', false)\">\n {{ translate('apiClient.responseBodyToggle.raw') }}\n </button>\n </div>\n</template>\n"],"mappings":";;;;;;;;;EAWA,MAAM,EAAE,cAAc,gBAAgB;;uBAGpC,mBAgBM,OAhBN,YAgBM,CAdJ,mBAMS,UAAA;IALP,OAAK,eAAA,CAAC,6BAA2B,EAAA,kCACW,QAAA,WAAU,CAAA,CAAA;IACtD,MAAK;IACJ,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAOA,KAAAA,MAAK,qBAAA,IAAA,GAAA,CAAA,MAAA,CAAA;sBACf,MAAA,SAAA,CAAS,CAAA,sCAAA,CAAA,GAAA,CAAA,GAEd,mBAMS,UAAA;IALP,OAAK,eAAA,CAAC,6BAA2B,EAAA,kCAAA,CACY,QAAA,WAAU,CAAA,CAAA;IACvD,MAAK;IACJ,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAOA,KAAAA,MAAK,qBAAA,KAAA,GAAA,CAAA,MAAA,CAAA;sBACf,MAAA,SAAA,CAAS,CAAA,kCAAA,CAAA,GAAA,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyVirtual.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyVirtual.vue"],"names":[],"mappings":"AAqEA,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC3C,CAAC;AAyGF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"ResponseBodyVirtual.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyVirtual.vue"],"names":[],"mappings":"AA2EA,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC3C,CAAC;AAgHF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyVirtual.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyVirtual.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarVirtualText } from '@scalar/components/virtual-text'\nimport { formatJsonOrYamlString } from '@scalar/oas-utils/helpers'\nimport { computed } from 'vue'\n\nimport { processResponseBody } from '@/v2/blocks/response-block/helpers/process-response-body'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nimport ResponseBodyDownload from './ResponseBodyDownload.vue'\n\nconst { content, data, headers } = defineProps<{\n content: string\n data: unknown\n headers: { name: string; value: string }[]\n}>()\n\nconst textContent = computed(() => formatJsonOrYamlString(content))\n\nconst responseBody = computed(() =>\n processResponseBody({\n data,\n headers,\n }),\n)\n</script>\n\n<template>\n <CollapsibleSection class=\"!max-h-100% response-body-virtual overflow-x-auto\">\n <template #title>Body</template>\n <template\n v-if=\"responseBody.dataUrl\"\n #actions>\n <ResponseBodyDownload\n :filename=\"responseBody.attachmentFilename\"\n :href=\"responseBody.dataUrl\"\n :type=\"responseBody.mimeType?.essence\" />\n </template>\n <div class=\"font-code text-xxs rounded-t border-x border-t px-2.5 py-1.5\">\n This response body is massive! Syntax highlighting won't work here.\n </div>\n <ScalarVirtualText\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n searchable\n :text=\"textContent\" />\n </CollapsibleSection>\n</template>\n\n<style>\n.response-body-virtual[data-headlessui-state='open'],\n.response-body-virtual[data-headlessui-state='open'] .diclosure-panel {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ResponseBodyVirtual.vue.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyVirtual.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarVirtualText } from '@scalar/components/virtual-text'\nimport { formatJsonOrYamlString } from '@scalar/oas-utils/helpers'\nimport { computed } from 'vue'\n\nimport { processResponseBody } from '@/v2/blocks/response-block/helpers/process-response-body'\nimport { CollapsibleSection } from '@/v2/components/layout'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport ResponseBodyDownload from './ResponseBodyDownload.vue'\n\nconst { content, data, headers } = defineProps<{\n content: string\n data: unknown\n headers: { name: string; value: string }[]\n}>()\n\nconst { translate } = useLocalization()\n\nconst textContent = computed(() => formatJsonOrYamlString(content))\n\nconst responseBody = computed(() =>\n processResponseBody({\n data,\n headers,\n }),\n)\n</script>\n\n<template>\n <CollapsibleSection class=\"!max-h-100% response-body-virtual overflow-x-auto\">\n <template #title>\n {{ translate('apiClient.responseBodyVirtual.body') }}\n </template>\n <template\n v-if=\"responseBody.dataUrl\"\n #actions>\n <ResponseBodyDownload\n :filename=\"responseBody.attachmentFilename\"\n :href=\"responseBody.dataUrl\"\n :type=\"responseBody.mimeType?.essence\" />\n </template>\n <div class=\"font-code text-xxs rounded-t border-x border-t px-2.5 py-1.5\">\n {{ translate('apiClient.responseBodyVirtual.largeBodyHint') }}\n </div>\n <ScalarVirtualText\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n searchable\n :text=\"textContent\" />\n </CollapsibleSection>\n</template>\n\n<style>\n.response-body-virtual[data-headlessui-state='open'],\n.response-body-virtual[data-headlessui-state='open'] .diclosure-panel {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n}\n</style>\n"],"mappings":""}
@@ -1,10 +1,12 @@
1
+ import { useLocalization } from "../../../features/localization/index.js";
1
2
  import CollapsibleSection_default from "../../../components/layout/CollapsibleSection.vue.js";
2
3
  import { processResponseBody } from "../helpers/process-response-body.js";
3
4
  import ResponseBodyDownload_default from "./ResponseBodyDownload.vue.js";
4
- import { computed, createBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, openBlock, unref, withCtx } from "vue";
5
+ import { computed, createBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, openBlock, toDisplayString, unref, withCtx } from "vue";
5
6
  import { formatJsonOrYamlString } from "@scalar/oas-utils/helpers";
6
7
  import { ScalarVirtualText } from "@scalar/components/virtual-text";
7
8
  //#region src/v2/blocks/response-block/components/ResponseBodyVirtual.vue?vue&type=script&setup=true&lang.ts
9
+ var _hoisted_1 = { class: "font-code text-xxs rounded-t border-x border-t px-2.5 py-1.5" };
8
10
  var ResponseBodyVirtual_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
9
11
  __name: "ResponseBodyVirtual",
10
12
  props: {
@@ -13,6 +15,7 @@ var ResponseBodyVirtual_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
13
15
  headers: {}
14
16
  },
15
17
  setup(__props) {
18
+ const { translate } = useLocalization();
16
19
  const textContent = computed(() => formatJsonOrYamlString(__props.content));
17
20
  const responseBody = computed(() => processResponseBody({
18
21
  data: __props.data,
@@ -20,8 +23,8 @@ var ResponseBodyVirtual_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
20
23
  }));
21
24
  return (_ctx, _cache) => {
22
25
  return openBlock(), createBlock(unref(CollapsibleSection_default), { class: "!max-h-100% response-body-virtual overflow-x-auto" }, createSlots({
23
- title: withCtx(() => [_cache[0] || (_cache[0] = createTextVNode("Body", -1))]),
24
- default: withCtx(() => [_cache[1] || (_cache[1] = createElementVNode("div", { class: "font-code text-xxs rounded-t border-x border-t px-2.5 py-1.5" }, " This response body is massive! Syntax highlighting won't work here. ", -1)), createVNode(unref(ScalarVirtualText), {
26
+ title: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.responseBodyVirtual.body")), 1)]),
27
+ default: withCtx(() => [createElementVNode("div", _hoisted_1, toDisplayString(unref(translate)("apiClient.responseBodyVirtual.largeBodyHint")), 1), createVNode(unref(ScalarVirtualText), {
25
28
  containerClass: "custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen",
26
29
  contentClass: "language-plaintext whitespace-pre font-code text-base",
27
30
  lineHeight: 20,
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseBodyVirtual.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyVirtual.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarVirtualText } from '@scalar/components/virtual-text'\nimport { formatJsonOrYamlString } from '@scalar/oas-utils/helpers'\nimport { computed } from 'vue'\n\nimport { processResponseBody } from '@/v2/blocks/response-block/helpers/process-response-body'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nimport ResponseBodyDownload from './ResponseBodyDownload.vue'\n\nconst { content, data, headers } = defineProps<{\n content: string\n data: unknown\n headers: { name: string; value: string }[]\n}>()\n\nconst textContent = computed(() => formatJsonOrYamlString(content))\n\nconst responseBody = computed(() =>\n processResponseBody({\n data,\n headers,\n }),\n)\n</script>\n\n<template>\n <CollapsibleSection class=\"!max-h-100% response-body-virtual overflow-x-auto\">\n <template #title>Body</template>\n <template\n v-if=\"responseBody.dataUrl\"\n #actions>\n <ResponseBodyDownload\n :filename=\"responseBody.attachmentFilename\"\n :href=\"responseBody.dataUrl\"\n :type=\"responseBody.mimeType?.essence\" />\n </template>\n <div class=\"font-code text-xxs rounded-t border-x border-t px-2.5 py-1.5\">\n This response body is massive! Syntax highlighting won't work here.\n </div>\n <ScalarVirtualText\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n searchable\n :text=\"textContent\" />\n </CollapsibleSection>\n</template>\n\n<style>\n.response-body-virtual[data-headlessui-state='open'],\n.response-body-virtual[data-headlessui-state='open'] .diclosure-panel {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;EAgBA,MAAM,cAAc,eAAe,uBAAuB,QAAA,OAAO,CAAC;EAElE,MAAM,eAAe,eACnB,oBAAoB;GAClB,MAAG,QAAA;GACH,SAAM,QAAA;EACR,CAAC,CACH;;uBAIE,YAmBqB,MAAA,0BAAA,GAAA,EAnBD,OAAM,oDAAmD,GAAA,YAAA;IAChE,OAAK,cAAK,CAAA,OAAA,OAAA,OAAA,KAAA,gBAAJ,QAAI,EAAA,EAAA,CAAA;2BAWf,CAAA,OAAA,OAAA,OAAA,KAFN,mBAEM,OAAA,EAFD,OAAM,+DAA8D,GAAC,yEAE1E,EAAA,IACA,YAKwB,MAAA,iBAAA,GAAA;KAJtB,gBAAe;KACf,cAAa;KACZ,YAAY;KACb,YAAA;KACC,MAAM,YAAA;;;OAfD,aAAA,MAAa,UAAA;UAClB;sBAI0C,CAH3C,YAG2C,8BAAA;KAFxC,UAAU,aAAA,MAAa;KACvB,MAAM,aAAA,MAAa;KACnB,MAAM,aAAA,MAAa,UAAU"}
1
+ {"version":3,"file":"ResponseBodyVirtual.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/response-block/components/ResponseBodyVirtual.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarVirtualText } from '@scalar/components/virtual-text'\nimport { formatJsonOrYamlString } from '@scalar/oas-utils/helpers'\nimport { computed } from 'vue'\n\nimport { processResponseBody } from '@/v2/blocks/response-block/helpers/process-response-body'\nimport { CollapsibleSection } from '@/v2/components/layout'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport ResponseBodyDownload from './ResponseBodyDownload.vue'\n\nconst { content, data, headers } = defineProps<{\n content: string\n data: unknown\n headers: { name: string; value: string }[]\n}>()\n\nconst { translate } = useLocalization()\n\nconst textContent = computed(() => formatJsonOrYamlString(content))\n\nconst responseBody = computed(() =>\n processResponseBody({\n data,\n headers,\n }),\n)\n</script>\n\n<template>\n <CollapsibleSection class=\"!max-h-100% response-body-virtual overflow-x-auto\">\n <template #title>\n {{ translate('apiClient.responseBodyVirtual.body') }}\n </template>\n <template\n v-if=\"responseBody.dataUrl\"\n #actions>\n <ResponseBodyDownload\n :filename=\"responseBody.attachmentFilename\"\n :href=\"responseBody.dataUrl\"\n :type=\"responseBody.mimeType?.essence\" />\n </template>\n <div class=\"font-code text-xxs rounded-t border-x border-t px-2.5 py-1.5\">\n {{ translate('apiClient.responseBodyVirtual.largeBodyHint') }}\n </div>\n <ScalarVirtualText\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n searchable\n :text=\"textContent\" />\n </CollapsibleSection>\n</template>\n\n<style>\n.response-body-virtual[data-headlessui-state='open'],\n.response-body-virtual[data-headlessui-state='open'] .diclosure-panel {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;EAiBA,MAAM,EAAE,cAAc,gBAAgB;EAEtC,MAAM,cAAc,eAAe,uBAAuB,QAAA,OAAO,CAAC;EAElE,MAAM,eAAe,eACnB,oBAAoB;GAClB,MAAG,QAAA;GACH,SAAM,QAAA;EACR,CAAC,CACH;;uBAIE,YAqBqB,MAAA,0BAAA,GAAA,EArBD,OAAM,oDAAmD,GAAA,YAAA;IAChE,OAAK,cACuC,CAAA,gBAAA,gBAAlD,MAAA,SAAA,CAAS,CAAA,oCAAA,CAAA,GAAA,CAAA,CAAA,CAAA;2BAYR,CAFN,mBAEM,OAFN,YAEM,gBADD,MAAA,SAAA,CAAS,CAAA,6CAAA,CAAA,GAAA,CAAA,GAEd,YAKwB,MAAA,iBAAA,GAAA;KAJtB,gBAAe;KACf,cAAa;KACZ,YAAY;KACb,YAAA;KACC,MAAM,YAAA;;;OAfD,aAAA,MAAa,UAAA;UAClB;sBAI0C,CAH3C,YAG2C,8BAAA;KAFxC,UAAU,aAAA,MAAa;KACvB,MAAM,aAAA,MAAa;KACnB,MAAM,aAAA,MAAa,UAAU"}