UNPKG

openapi-explorer

Version:

OpenAPI Explorer - API viewer with dynamically generated components, documentation, and interaction console

183 lines (179 loc) 14.4 kB
"use strict"; exports.__esModule = true; exports.default = void 0; var _lit = require("lit"); var _unsafeHtml = require("lit/directives/unsafe-html.js"); var _schemaUtils = require("../utils/schema-utils.js"); var _commonUtils = require("../utils/common-utils.js"); var _index = require("../languages/index.js"); var _fontStyles = _interopRequireDefault(require("../styles/font-styles.js")); var _flexStyles = _interopRequireDefault(require("../styles/flex-styles.js")); var _tableStyles = _interopRequireDefault(require("../styles/table-styles.js")); var _inputStyles = _interopRequireDefault(require("../styles/input-styles.js")); var _tabStyles = _interopRequireDefault(require("../styles/tab-styles.js")); var _borderStyles = _interopRequireDefault(require("../styles/border-styles.js")); var _schemaStyles = _interopRequireDefault(require("../styles/schema-styles.js")); var _prismStyles = _interopRequireDefault(require("../styles/prism-styles.js")); require("./schema-tree.js"); require("./schema-table.js"); require("./syntax-highlighter.js"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class ApiResponse extends _lit.LitElement { constructor() { super(); this.selectedStatus = ''; this.headersForEachRespStatus = {}; this.mimeResponsesForEachStatus = {}; this.activeSchemaTab = 'model'; } static get properties() { return { callback: { type: String }, responses: { type: Object }, parser: { type: Object }, includeNulls: { type: Boolean, attribute: 'display-nulls', converter(value) { return value === 'true'; } }, schemaStyle: { type: String, attribute: 'schema-style' }, renderStyle: { type: String, attribute: 'render-style' }, selectedStatus: { type: String, attribute: 'selected-status' }, selectedMimeType: { type: String, attribute: 'selected-mime-type' }, activeSchemaTab: { type: String, attribute: 'active-schema-tab' }, schemaExpandLevel: { type: Number, attribute: 'schema-expand-level' }, schemaHideWriteOnly: { type: String, attribute: 'schema-hide-write-only' } }; } static finalizeStyles() { return [_schemaStyles.default, _fontStyles.default, _flexStyles.default, _tabStyles.default, _tableStyles.default, _inputStyles.default, _borderStyles.default, _prismStyles.default, (0, _lit.css)`.resp-head{vertical-align:middle;padding:16px 0 8px}.resp-head.divider{border-top:1px solid var(--border-color);margin-top:10px}.resp-status{font-weight:700;font-size:calc(var(--font-size-small) + 1px)}.resp-descr{font-size:calc(var(--font-size-small) + 1px)}.top-gap{margin-top:16px}.example-panel{font-size:var(--font-size-small);margin:0}.generic-tree{background:var(--bg2,#333);color:var(--fg,#fff)}.example-panel.generic-tree{margin-top:8px}pre.generic-tree{border:none;padding:8px 10px 10px}.example-panel select{margin-left:8px;padding-top:8px;min-width:100px;max-width:100%}.example-panel .example{padding:0 12px}.focused-mode,.read-mode{padding-top:3rem;margin-top:12px;border-top:1px dashed var(--border-color)}`]; } render() { return (0, _lit.html)` <div class="col regular-font response-panel ${this.renderStyle}-mode"> <div class="${this.callback === 'true' ? 'tiny-title' : 'req-res-title'}" role="heading" aria-level="${this.renderStyle === 'focused' ? 3 : 4}"> ${this.callback === 'true' ? (0, _index.getI18nText)('operations.callback-response') : (0, _index.getI18nText)('operations.response')} </div> <div> ${this.responseTemplate()} <div> </div> </div></div>`; } resetSelection() { this.selectedStatus = ''; this.selectedMimeType = ''; } /* eslint-disable indent */ responseTemplate() { if (!this.responses) { return ''; } for (const statusCode in this.responses) { if (!this.selectedStatus) { this.selectedStatus = statusCode; } const allMimeResp = {}; for (const mimeResp in this.responses[statusCode] && this.responses[statusCode].content) { const mimeRespObj = this.responses[statusCode].content[mimeResp]; if (!this.selectedMimeType) { this.selectedMimeType = mimeResp; } // Generate Schema const schemaTree = (0, _schemaUtils.schemaInObjectNotation)(mimeRespObj.schema, { includeNulls: this.includeNulls }); // Generate Example const respExamples = (0, _schemaUtils.generateExample)(mimeRespObj.examples || '', mimeRespObj.example || '', mimeRespObj.schema, mimeResp, true, false, mimeResp.includes('json') ? 'json' : 'text'); allMimeResp[mimeResp] = { description: this.responses[statusCode].description, examples: respExamples, selectedExample: respExamples[0] && respExamples[0].exampleId || '', schemaTree }; } // Headers for each response status const tempHeaders = []; for (const key in this.responses[statusCode] && this.responses[statusCode].headers) { tempHeaders.push({ name: key, ...this.responses[statusCode].headers[key] }); } this.headersForEachRespStatus[statusCode] = tempHeaders; this.mimeResponsesForEachStatus[statusCode] = allMimeResp; } return (0, _lit.html)`<div class="row" style="flex-wrap:wrap" role="group"> ${Object.keys(this.responses).map(respStatus => (0, _lit.html)` ${respStatus === '$$ref' // Swagger-Client parser creates '$$ref' object if JSON references are used to create responses - this should be ignored ? '' : (0, _lit.html)` <button @click="${() => { this.selectedStatus = respStatus; if (this.responses[respStatus].content && Object.keys(this.responses[respStatus].content)[0]) { this.selectedMimeType = Object.keys(this.responses[respStatus].content)[0]; } else { this.selectedMimeType = undefined; } }}" aria-current="${this.selectedStatus === respStatus}" class="m-btn small ${this.selectedStatus === respStatus ? 'primary' : ''}" part="btn--resp ${this.selectedStatus === respStatus ? 'btn-fill--resp' : 'btn-outline--resp'} btn-response-status" style="margin:8px 4px 0 0;text-transform:capitalize"> ${respStatus} </button>`}`)} </div> ${Object.keys(this.responses).map(status => (0, _lit.html)` <div style="display:${status === this.selectedStatus ? 'block' : 'none'}"> <div class="top-gap"> <span class="resp-descr m-markdown">${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(this.responses[status] && this.responses[status].description || ''))}</span> ${this.headersForEachRespStatus[status] && this.headersForEachRespStatus[status].length > 0 ? (0, _lit.html)`${this.responseHeaderListTemplate(this.headersForEachRespStatus[status])}` : ''} </div> ${Object.keys(this.mimeResponsesForEachStatus[status]).length === 0 ? '' : (0, _lit.html)` <div class="tab-panel col"> <div class="tab-buttons row" role="group" @click="${e => { if (e.target.tagName.toLowerCase() === 'button') { this.activeSchemaTab = e.target.dataset.tab; } }}"> <button class="tab-btn ${this.activeSchemaTab === 'model' ? 'active' : ''}" aria-current="${this.activeSchemaTab === 'model'}" data-tab="model">${(0, _index.getI18nText)('operations.model')}</button> <button class="tab-btn ${this.activeSchemaTab !== 'model' ? 'active' : ''}" aria-current="${this.activeSchemaTab !== 'model'}" data-tab="body">${(0, _index.getI18nText)('operations.example')}</button> <div style="flex:1"></div> ${Object.keys(this.mimeResponsesForEachStatus[status]).length === 1 ? (0, _lit.html)`<span class="small-font-size gray-text" style="align-self:center;margin-top:8px"> ${Object.keys(this.mimeResponsesForEachStatus[status])[0]} </span>` : (0, _lit.html)`${this.mimeTypeDropdownTemplate(Object.keys(this.mimeResponsesForEachStatus[status]))}`} </div> ${this.activeSchemaTab === 'body' ? (0, _lit.html)`<div class="tab-content col" style="flex:1"> ${this.mimeExampleTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} </div>` : (0, _lit.html)`<div class="tab-content col" style="flex:1"> ${this.mimeSchemaTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} </div>`} </div> `}</div>`)} `; } responseHeaderListTemplate(respHeaders) { return (0, _lit.html)` <div style="padding:16px 0 8px 0" class="resp-headers small-font-size bold-text">${(0, _index.getI18nText)('operations.response-headers')}</div> <table role="presentation" style="border-collapse:collapse;margin-bottom:16px;border:1px solid var(--border-color);border-radius:var(--border-radius)" class="small-font-size mono-font"> ${respHeaders.map(v => { var _ref, _typeData$example; const typeData = (0, _schemaUtils.getTypeInfo)(v, { enableExampleGeneration: true }); return (0, _lit.html)` <tr> <td style="padding:8px;vertical-align:baseline;min-width:160px;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${v.name || ''} </td> <td class="${(typeData === null || typeData === void 0 ? void 0 : typeData.cssType) || ''}" style="padding:4px;vertical-align:baseline;min-width:100px;padding:0 5px;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${(typeData === null || typeData === void 0 ? void 0 : typeData.format) || (typeData === null || typeData === void 0 ? void 0 : typeData.type) || ''} </td> <td style="padding:8px;vertical-align:baseline;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> <div class="m-markdown-small regular-font">${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(v.description || ''))}</div> </td> <td style="padding:8px;vertical-align:baseline;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${(_ref = (_typeData$example = typeData === null || typeData === void 0 ? void 0 : typeData.example) !== null && _typeData$example !== void 0 ? _typeData$example : typeData === null || typeData === void 0 ? void 0 : typeData.default) !== null && _ref !== void 0 ? _ref : ''} </td> </tr> `; })} </table>`; } mimeTypeDropdownTemplate(mimeTypes) { return (0, _lit.html)` <select aria-label="mime type" @change="${e => { this.selectedMimeType = e.target.value; }}" style="margin-bottom:-1px;z-index:1"> ${mimeTypes.map(mimeType => (0, _lit.html)`<option value="${mimeType}" ?selected="${mimeType === this.selectedMimeType}"> ${mimeType} </option>`)} </select>`; } onSelectExample(e) { const exampleContainerEl = e.target.closest('.example-panel'); const exampleEls = [...exampleContainerEl.querySelectorAll('.example')]; exampleEls.forEach(v => { v.style.display = v.dataset.example === e.target.value ? 'block' : 'none'; }); } mimeExampleTemplate(mimeRespDetails) { if (!mimeRespDetails) { return (0, _lit.html)` <pre style="color:var(--red)" class="example-panel border-top"> No example provided </pre> `; } return (0, _lit.html)` ${mimeRespDetails.examples.length === 1 ? (0, _lit.html)` ${mimeRespDetails.examples[0].exampleSummary && mimeRespDetails.examples[0].exampleSummary.length > 80 ? (0, _lit.html)`<div style="padding:4px 0"> ${mimeRespDetails.examples[0].exampleSummary} </div>` : ''} ${mimeRespDetails.examples[0].exampleDescription ? (0, _lit.html)`<div class="m-markdown-small" style="padding:4px 0"> ${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(mimeRespDetails.examples[0].exampleDescription || ''))} </div>` : ''} <syntax-highlighter class="example-panel generic-tree pad-top-8" mime-type="${mimeRespDetails.examples[0].exampleType}" .content="${mimeRespDetails.examples[0].exampleValue}">` : (0, _lit.html)` <span class="example-panel generic-tree ${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top pad-top-8'}"> <select aria-label="response body example" @change="${e => this.onSelectExample(e)}"> ${mimeRespDetails.examples.map(v => (0, _lit.html)`<option value="${v.exampleId}" ?selected="${v.exampleId === mimeRespDetails.selectedExample}"> ${!v.exampleSummary || v.exampleSummary.length > 80 ? v.exampleId : v.exampleSummary} </option>`)} </select> ${mimeRespDetails.examples.map(v => (0, _lit.html)` <div class="example" data-example="${v.exampleId}" style="display:${v.exampleId === mimeRespDetails.selectedExample ? 'block' : 'none'}"> ${v.exampleSummary && v.exampleSummary.length > 80 ? (0, _lit.html)`<div style="padding:4px 0"> ${v.exampleSummary} </div>` : ''} ${v.exampleDescription && v.exampleDescription !== v.exampleSummary ? (0, _lit.html)`<div class="m-markdown-small" style="padding:4px 0"> ${(0, _unsafeHtml.unsafeHTML)((0, _commonUtils.toMarkdown)(v.exampleDescription || ''))} </div>` : ''} <syntax-highlighter mime-type="${v.exampleType}" .content="${v.exampleValue}"> </div> `)} </span> `} `; } mimeSchemaTemplate(mimeRespDetails) { if (!mimeRespDetails) { return (0, _lit.html)` <pre style="color:var(--red)" class="${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top'}"> Schema not found</pre> `; } return (0, _lit.html)` ${this.schemaStyle === 'table' ? (0, _lit.html)` <schema-table render-style="${this.renderStyle}" .data="${mimeRespDetails.schemaTree}" class="example-panel ${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top pad-top-8'}" schema-expand-level="${this.schemaExpandLevel}" schema-hide-read-only="false" schema-hide-write-only="${this.schemaHideWriteOnly}" exportparts="schema-key, schema-type, schema-description, schema-table-header"> </schema-table> ` : (0, _lit.html)` <schema-tree render-style="${this.renderStyle}" .data="${mimeRespDetails.schemaTree}" class="example-panel ${this.renderStyle === 'read' ? 'border pad-8-16' : 'pad-top-8'}" schema-expand-level="${this.schemaExpandLevel}" schema-hide-read-only="false" schema-hide-write-only="${this.schemaHideWriteOnly}" exportparts="schema-key, schema-type, schema-description"> </schema-tree>`}`; } /* eslint-enable indent */ } // Register the element with the browser exports.default = ApiResponse; if (!customElements.get('openapi-explorer')) { customElements.define('api-response', ApiResponse); }