diff --git a/src/core/index.js b/src/core/index.js index c3725f6644b..499c81c6539 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -29,6 +29,7 @@ import DownloadUrlPlugin from "./plugins/download-url" import SafeRenderPlugin from "./plugins/safe-render" import { parseSearch } from "./utils" +import { convertConfigValues } from "./utils/convertConfigValues" import win from "./window" // eslint-disable-next-line no-undef @@ -134,7 +135,7 @@ export default function SwaggerUI(opts) { } } - let queryConfig = opts.queryConfigEnabled ? parseSearch() : {} + let queryConfig = opts.queryConfigEnabled ? convertConfigValues(parseSearch()) : {} const domNode = opts.domNode delete opts.domNode diff --git a/src/core/utils/convertConfigValues.js b/src/core/utils/convertConfigValues.js new file mode 100644 index 00000000000..54ad62d7674 --- /dev/null +++ b/src/core/utils/convertConfigValues.js @@ -0,0 +1,74 @@ +/** + * @prettier + */ +const booleanConfigs = [ + "deepLinking", + "displayOperationId", + "displayRequestDuration", + "filter", + "persistAuthorization", + "requestSnippetsEnabled", + "showCommonExtensions", + "showExtensions", + "showMutatedRequest", + "syntaxHighlight.activated", + "tryItOutEnabled", + "withCredentials", +] +const numberConfigs = [ + "defaultModelExpandDepth", + "defaultModelsExpandDepth", + "maxDisplayedTags", +] +const objectConfigs = ["syntaxHighlight", "requestSnippets"] +const arrayConfigs = ["request.curlOptions", "supportedSubmitMethods"] + +const convertValue = (key, value) => { + const isBoolean = booleanConfigs.includes(key) + const isNumber = numberConfigs.includes(key) + const isObject = objectConfigs.includes(key) + const isArray = arrayConfigs.includes(key) + + if (key === "validatorUrl") { + return value === "null" ? null : value + } + + if (isBoolean) { + return value === "true" ? true : value === "false" ? false : value + } + + if (isNumber) { + const parsedValue = parseInt(value) + return isNaN(parsedValue) ? value : parsedValue + } + + if (isObject) { + if (key === "syntaxHighlight" && value === "false") return false + try { + const parsedValue = JSON.parse(value) + return typeof parsedValue === "object" && !Array.isArray(parsedValue) + ? parsedValue + : value + } catch (e) { + return value + } + } + + if (isArray) { + try { + const parsedValue = JSON.parse(value) + return Array.isArray(parsedValue) ? parsedValue : value + } catch (e) { + return value + } + } + + return value +} + +export const convertConfigValues = (config) => { + Object.entries(config).forEach(([key, value]) => { + config[key] = convertValue(key, value) + }) + return config +} diff --git a/test/e2e-cypress/e2e/features/syntax-highlighting-json.cy.js b/test/e2e-cypress/e2e/features/syntax-highlighting-json.cy.js index 236aabaa761..be1dbd473ec 100644 --- a/test/e2e-cypress/e2e/features/syntax-highlighting-json.cy.js +++ b/test/e2e-cypress/e2e/features/syntax-highlighting-json.cy.js @@ -8,17 +8,29 @@ describe("Syntax Highlighting for JSON value cases", () => { describe("OAS 2", () => { it("should render full syntax highlighted string in Request (param body) example", () => { cy.visit("/?url=/documents/features/syntax-highlighting-json-oas2.yaml") - .get("#operations-default-post_setServices") - .click() - .get(".body-param__example > .language-json > :nth-child(10)") - .should("have.text", "\"79daf5b4-aa4b-1452-eae5-42c231477ba7\"") + .get("#operations-default-post_setServices") + .click() + .get(".body-param__example > .language-json > :nth-child(10)") + .should("have.text", '"79daf5b4-aa4b-1452-eae5-42c231477ba7"') }) it("should render full syntax highlighted string in Response example", () => { cy.visit("/?url=/documents/features/syntax-highlighting-json-oas2.yaml") - .get("#operations-default-post_setServices") - .click() - .get(".example > .language-json > :nth-child(28)") - .should("have.text", "\"5ff06f632bb165394501b05d3a833355\"") + .get("#operations-default-post_setServices") + .click() + .get(".example > .language-json > :nth-child(28)") + .should("have.text", '"5ff06f632bb165394501b05d3a833355"') + }) + it("should not render syntax highlighted string when syntaxHighlight.activated is set to false", () => { + cy.visit( + "/?syntaxHighlight.activated=false&url=/documents/features/syntax-highlighting-json-oas2.yaml" + ) + .get("#operations-default-post_setServices") + .click() + .get(".example > .language-json") + .should("not.exist") + .get(".example") + .contains('"5ff06f632bb165394501b05d3a833355"') + .should("exist") }) }) describe("OAS 3", () => { @@ -27,14 +39,26 @@ describe("Syntax Highlighting for JSON value cases", () => { .get("#operations-default-post_setServices") .click() .get(".body-param__example > .language-json > :nth-child(15)") - .should("have.text", "\"22a124b4-594b-4452-bdf5-fc3ef1477ba7\"") + .should("have.text", '"22a124b4-594b-4452-bdf5-fc3ef1477ba7"') }) it("should render full syntax highlighted string in Response example", () => { cy.visit("/?url=/documents/features/syntax-highlighting-json-oas3.yaml") .get("#operations-default-post_setServices") .click() .get(".example > .language-json > :nth-child(33)") - .should("have.text", "\"f0009babde9dbe204540d79cf754408e\"") + .should("have.text", '"f0009babde9dbe204540d79cf754408e"') + }) + it("should not render syntax highlighted string when syntaxHighlight is set to false", () => { + cy.visit( + "/?syntaxHighlight=false&url=/documents/features/syntax-highlighting-json-oas3.yaml" + ) + .get("#operations-default-post_setServices") + .click() + .get(".example > .language-json") + .should("not.exist") + .get(".example") + .contains('"f0009babde9dbe204540d79cf754408e"') + .should("exist") }) }) }) diff --git a/test/unit/core/utils.js b/test/unit/core/utils.js index a733543e63e..fcbe977d2d5 100644 --- a/test/unit/core/utils.js +++ b/test/unit/core/utils.js @@ -37,6 +37,10 @@ import { safeBuildUrl, } from "core/utils/url" +import { + convertConfigValues +} from "core/utils/convertConfigValues" + import win from "core/window" import { afterAll, beforeAll, expect, jest } from "@jest/globals" @@ -1776,4 +1780,54 @@ describe("utils", () => { expect(createCodeChallenge(codeVerifier)).toBe(expectedCodeChallenge) }) }) + + describe("convertConfigValues", () => { + it("should convert stringified `true` and `false` values to boolean" , () => { + const config = { deepLinking: "true", tryItOutEnabled: "false" } + + const expectedConfig = { deepLinking: true, tryItOutEnabled: false } + + expect(convertConfigValues(config)).toStrictEqual(expectedConfig) + }) + + it("should convert stringified number values to number" , () => { + const config = { defaultModelExpandDepth: "5", defaultModelsExpandDepth: "-1" } + + const expectedConfig = { defaultModelExpandDepth: 5, defaultModelsExpandDepth: -1 } + + expect(convertConfigValues(config)).toStrictEqual(expectedConfig) + }) + + it("should convert stringified number values to number" , () => { + const config = { defaultModelExpandDepth: "5", defaultModelsExpandDepth: "-1" } + + const expectedConfig = { defaultModelExpandDepth: 5, defaultModelsExpandDepth: -1 } + + expect(convertConfigValues(config)).toStrictEqual(expectedConfig) + }) + + it("should convert stringified array values to arrays" , () => { + const config = { supportedSubmitMethods: '["get", "post"]' } + + const expectedConfig = { supportedSubmitMethods: ["get", "post"] } + + expect(convertConfigValues(config)).toStrictEqual(expectedConfig) + }) + + it("should convert stringified object values to objects" , () => { + const config = { syntaxHighlight: '{"theme":"monokai"}' } + + const expectedConfig = { syntaxHighlight: { theme: "monokai" } } + + expect(convertConfigValues(config)).toStrictEqual(expectedConfig) + }) + + it("should not convert string values" , () => { + const config = { defaultModelRendering: "model" } + + const expectedConfig = { defaultModelRendering: "model" } + + expect(convertConfigValues(config)).toStrictEqual(expectedConfig) + }) + }) })