diff --git a/package-lock.json b/package-lock.json index 395ae007..fd61b5c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,7 +45,8 @@ "react-use": "^17.4.0", "slugify": "^1.6.6", "tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1", - "uuid": "^9.0.0" + "uuid": "^9.0.0", + "xml-formatter": "^3.6.2" }, "devDependencies": { "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", @@ -11033,6 +11034,25 @@ "node": ">=4" } }, + "node_modules/xml-formatter": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-3.6.2.tgz", + "integrity": "sha512-enWhevZNOwffZFUhzl1WMcha8lFLZUgJ7NzFs5Ug4ZOFCoNheGYXz1J9Iz/e+cTn9rCkuT1GwTacz+YlmFHOGw==", + "dependencies": { + "xml-parser-xo": "^4.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/xml-parser-xo": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-4.1.1.tgz", + "integrity": "sha512-Ggf2y90+Y6e9IK5hoPuembVHJ03PhDSdhldEmgzbihzu9k0XBo0sfcFxaSi4W1PlUSSI1ok+MJ0JCXUn+U4Ilw==", + "engines": { + "node": ">= 14" + } + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index 6cf6073c..af34c249 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,8 @@ "react-use": "^17.4.0", "slugify": "^1.6.6", "tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1", - "uuid": "^9.0.0" + "uuid": "^9.0.0", + "xml-formatter": "^3.6.2" }, "devDependencies": { "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", diff --git a/src-web/components/ResponsePane.tsx b/src-web/components/ResponsePane.tsx index af434376..ef72b175 100644 --- a/src-web/components/ResponsePane.tsx +++ b/src-web/components/ResponsePane.tsx @@ -174,8 +174,6 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ ) : contentType?.match(/csv|tab-separated/) ? ( ) : ( - // ) : contentType?.startsWith('application/json') ? ( - // )} diff --git a/src-web/components/responseViewers/TextViewer.tsx b/src-web/components/responseViewers/TextViewer.tsx index 7cad80c2..fc2b7a74 100644 --- a/src-web/components/responseViewers/TextViewer.tsx +++ b/src-web/components/responseViewers/TextViewer.tsx @@ -6,7 +6,7 @@ import { useFilterResponse } from '../../hooks/useFilterResponse'; import { useResponseBodyText } from '../../hooks/useResponseBodyText'; import { useResponseContentType } from '../../hooks/useResponseContentType'; import { useToggle } from '../../hooks/useToggle'; -import { tryFormatJson } from '../../lib/formatters'; +import { tryFormatJson, tryFormatXml } from '../../lib/formatters'; import type { HttpResponse } from '../../lib/models'; import { Editor } from '../core/Editor'; import { IconButton } from '../core/IconButton'; @@ -23,7 +23,12 @@ export function TextViewer({ response, pretty }: Props) { const contentType = useResponseContentType(response); const rawBody = useResponseBodyText(response) ?? ''; - const formattedBody = pretty && contentType?.includes('json') ? tryFormatJson(rawBody) : rawBody; + const formattedBody = + pretty && contentType?.includes('json') + ? tryFormatJson(rawBody) + : pretty && contentType?.includes('xml') + ? tryFormatXml(rawBody) + : rawBody; const filteredResponse = useFilterResponse({ filter: filterText, responseId: response.id }); const body = filteredResponse ?? formattedBody; diff --git a/src-web/lib/formatters.ts b/src-web/lib/formatters.ts index 18e8f2dd..b967e458 100644 --- a/src-web/lib/formatters.ts +++ b/src-web/lib/formatters.ts @@ -1,3 +1,5 @@ +import xmlFormat from 'xml-formatter'; + export function tryFormatJson(text: string, pretty = true): string { try { if (pretty) return JSON.stringify(JSON.parse(text), null, 2); @@ -6,3 +8,11 @@ export function tryFormatJson(text: string, pretty = true): string { return text; } } + +export function tryFormatXml(text: string): string { + try { + return xmlFormat(text, { throwOnFailure: true, strictMode: false }); + } catch (_) { + return text; + } +}