rapidoc 11.0.0 → 12.0.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.
- package/README.md +46 -31
- package/dist/rapidoc-min.js +1424 -213
- package/dist/rapidoc-static-min.js +13542 -0
- package/package.json +48 -34
- package/src/components/api-request.ts +869 -0
- package/src/components/api-response.ts +509 -0
- package/src/components/json-tree.ts +171 -0
- package/src/components/schema-base-element.ts +315 -0
- package/src/components/schema-table.ts +430 -0
- package/src/components/schema-tree.ts +386 -0
- package/src/components/tag-input.ts +184 -0
- package/src/index.js +6 -0
- package/src/oauth-receiver.ts +29 -0
- package/src/rapidoc-mini.ts +582 -0
- package/src/rapidoc.ts +1808 -0
- package/src/static/index.d.ts +149 -0
- package/src/static/index.js +62 -0
- package/src/static/navigation.js +497 -0
- package/src/static/render.js +490 -0
- package/src/static/serializer.js +216 -0
- package/src/styles/auth-styles.js +318 -0
- package/src/styles/border-styles.js +24 -0
- package/src/styles/css-bundle.js +129 -0
- package/src/styles/custom-styles.js +8 -0
- package/src/styles/dialog-box-styles.js +102 -0
- package/src/styles/endpoint-styles.js +559 -0
- package/src/styles/flex-styles.js +16 -0
- package/src/styles/font-styles.js +432 -0
- package/src/styles/info-styles.js +36 -0
- package/src/styles/input-styles.js +555 -0
- package/src/styles/layout-styles.js +396 -0
- package/src/styles/microlighter-styles.js +99 -0
- package/src/styles/nav-styles.js +609 -0
- package/src/styles/param-list-styles.js +261 -0
- package/src/styles/schema-styles.js +288 -0
- package/src/styles/tab-styles.js +106 -0
- package/src/styles/theme-tokens.js +582 -0
- package/src/templates/advanced-search-dialog-template.js +94 -0
- package/src/templates/api-response-template.js +219 -0
- package/src/templates/callback-template.js +86 -0
- package/src/templates/code-samples-template.js +52 -0
- package/src/templates/components-template.js +86 -0
- package/src/templates/downloads-template.js +85 -0
- package/src/templates/endpoint-template.js +386 -0
- package/src/templates/expanded-endpoint-template.js +266 -0
- package/src/templates/focused-endpoint-template.js +145 -0
- package/src/templates/header-template.js +92 -0
- package/src/templates/logo-template.js +21 -0
- package/src/templates/main-body-template.js +102 -0
- package/src/templates/navbar-template.js +489 -0
- package/src/templates/overview-template.js +104 -0
- package/src/templates/request-body-template.js +651 -0
- package/src/templates/request-params-template.js +474 -0
- package/src/templates/security-scheme-template.js +1263 -0
- package/src/templates/server-template.js +152 -0
- package/src/utils/auto-color-scheme.js +99 -0
- package/src/utils/bind-navbar.js +175 -0
- package/src/utils/color-utils.js +59 -0
- package/src/utils/common-utils.js +191 -0
- package/src/utils/curl-utils.js +123 -0
- package/src/utils/highlighter.js +416 -0
- package/src/utils/markdown-utils.js +110 -0
- package/src/utils/mcp/common.js +467 -0
- package/src/utils/mcp/generators/csharp.js +242 -0
- package/src/utils/mcp/generators/go.js +298 -0
- package/src/utils/mcp/generators/java.js +330 -0
- package/src/utils/mcp/generators/python.js +248 -0
- package/src/utils/mcp/generators/rust.js +281 -0
- package/src/utils/mcp/generators/typescript.js +290 -0
- package/src/utils/mcp-generator.js +143 -0
- package/src/utils/mock-interceptor.js +508 -0
- package/src/utils/oauth-utils.js +87 -0
- package/src/utils/request-utils.js +203 -0
- package/src/utils/response-utils.js +203 -0
- package/src/utils/sanitize.js +57 -0
- package/src/utils/schema-utils.js +1927 -0
- package/src/utils/slugger.js +189 -0
- package/src/utils/spec-parser.js +915 -0
- package/src/utils/url-utils.js +211 -0
- package/src/utils/xml-utils.js +61 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders the interactive API response panel (status, headers, body, blob actions),
|
|
3
|
+
* live cURL preview/copy, and the execute/Try action controls for <api-request>.
|
|
4
|
+
*/
|
|
5
|
+
import { html } from "lit";
|
|
6
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
7
|
+
import { copyToClipboard, downloadResource, viewResource } from "~/utils/common-utils";
|
|
8
|
+
|
|
9
|
+
export function curlSyntaxTemplate(display = "flex") {
|
|
10
|
+
return html`
|
|
11
|
+
<div class="col m-markdown" style="flex:1; display:${display}; position:relative; max-width: 100%;">
|
|
12
|
+
<button
|
|
13
|
+
class="btn btn-sm btn-outline toolbar-btn"
|
|
14
|
+
style="position:absolute; top:12px; right:8px"
|
|
15
|
+
@click="${(e) => {
|
|
16
|
+
copyToClipboard(this.curlSyntax.trim().replace(/\\$/, ""), e);
|
|
17
|
+
}}"
|
|
18
|
+
part="btn btn-outline btn-copy"
|
|
19
|
+
>
|
|
20
|
+
Copy
|
|
21
|
+
</button>
|
|
22
|
+
<pre style="white-space:pre"><code class="language-shell">${this.curlSyntax.trim().replace(/\\$/, "")}</code></pre>
|
|
23
|
+
</div>
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function apiResponseTabTemplate() {
|
|
28
|
+
let responseFormat = "";
|
|
29
|
+
let responseContent = "";
|
|
30
|
+
if (!this.responseIsBlob) {
|
|
31
|
+
if (
|
|
32
|
+
this.responseHeaders.includes("application/x-ndjson") ||
|
|
33
|
+
this.responseHeaders.includes("json")
|
|
34
|
+
) {
|
|
35
|
+
responseFormat = "json";
|
|
36
|
+
} else if (this.responseHeaders.includes("html") || this.responseHeaders.includes("xml")) {
|
|
37
|
+
responseFormat = "html";
|
|
38
|
+
} else {
|
|
39
|
+
responseFormat = "text";
|
|
40
|
+
}
|
|
41
|
+
responseContent = html`<code class="language-${responseFormat}">${this.responseText}</code>`;
|
|
42
|
+
}
|
|
43
|
+
return html` <div class="row" style="font-size:var(--font-size-small); margin:5px 0; justify-content:space-between; align-items:center;">
|
|
44
|
+
<div class="response-message ${this.responseStatus}">Response Status: ${this.responseMessage}</div>
|
|
45
|
+
<button class="btn btn-outline" part="btn btn-outline btn-clear-response" @click="${this.clearResponseData}">CLEAR RESPONSE</button>
|
|
46
|
+
</div>
|
|
47
|
+
<div part="tab-panel" class="tab-panel col">
|
|
48
|
+
<div
|
|
49
|
+
id="tab_buttons"
|
|
50
|
+
part="tab-btn-row"
|
|
51
|
+
class="tab-buttons row"
|
|
52
|
+
@click="${(e) => {
|
|
53
|
+
if (
|
|
54
|
+
e.target.classList.contains("tab-btn") === false &&
|
|
55
|
+
e.target.classList.contains("tab") === false
|
|
56
|
+
) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.activeResponseTab = e.target.dataset.tab;
|
|
60
|
+
}}"
|
|
61
|
+
>
|
|
62
|
+
<button part="tab-btn" class="tab-btn ${this.activeResponseTab === "response" ? "active" : ""}" data-tab="response">
|
|
63
|
+
RESPONSE
|
|
64
|
+
</button>
|
|
65
|
+
<button part="tab-btn" class="tab-btn ${this.activeResponseTab === "headers" ? "active" : ""}" data-tab="headers">
|
|
66
|
+
RESPONSE HEADERS
|
|
67
|
+
</button>
|
|
68
|
+
${
|
|
69
|
+
this.showCurlBeforeTry === "true"
|
|
70
|
+
? ""
|
|
71
|
+
: html`<button part="tab-btn" class="tab-btn ${this.activeResponseTab === "curl" ? "active" : ""}" data-tab="curl">
|
|
72
|
+
CURL
|
|
73
|
+
</button>`
|
|
74
|
+
}
|
|
75
|
+
</div>
|
|
76
|
+
${
|
|
77
|
+
this.responseIsBlob
|
|
78
|
+
? html`<div
|
|
79
|
+
part="tab-content"
|
|
80
|
+
class="tab-content col"
|
|
81
|
+
style="flex:1; display:${this.activeResponseTab === "response" ? "flex" : "none"};"
|
|
82
|
+
>
|
|
83
|
+
${
|
|
84
|
+
this.responseBlobType === "image"
|
|
85
|
+
? html`<img style="max-height:var(--resp-area-height); object-fit:contain;" class="mar-top-8" src="${ifDefined(this.responseBlobUrl)}"></img>`
|
|
86
|
+
: ""
|
|
87
|
+
}
|
|
88
|
+
<button
|
|
89
|
+
class="btn btn-outline mar-top-8"
|
|
90
|
+
style="width:135px"
|
|
91
|
+
@click="${() => {
|
|
92
|
+
downloadResource(this.responseBlobUrl, this.respContentDisposition);
|
|
93
|
+
}}"
|
|
94
|
+
part="btn btn-outline"
|
|
95
|
+
>
|
|
96
|
+
DOWNLOAD
|
|
97
|
+
</button>
|
|
98
|
+
${
|
|
99
|
+
this.responseBlobType === "view" || this.responseBlobType === "image"
|
|
100
|
+
? html`<button
|
|
101
|
+
class="btn btn-outline mar-top-8"
|
|
102
|
+
style="width:135px"
|
|
103
|
+
@click="${() => {
|
|
104
|
+
viewResource(this.responseBlobUrl);
|
|
105
|
+
}}"
|
|
106
|
+
part="btn btn-outline"
|
|
107
|
+
>
|
|
108
|
+
VIEW (NEW TAB)
|
|
109
|
+
</button>`
|
|
110
|
+
: ""
|
|
111
|
+
}
|
|
112
|
+
</div>`
|
|
113
|
+
: html`<div
|
|
114
|
+
part="tab-content"
|
|
115
|
+
class="tab-content col m-markdown"
|
|
116
|
+
style="flex:1; display:${this.activeResponseTab === "response" ? "flex" : "none"};"
|
|
117
|
+
>
|
|
118
|
+
<button
|
|
119
|
+
class="btn btn-sm btn-outline toolbar-btn"
|
|
120
|
+
@click="${(e) => {
|
|
121
|
+
copyToClipboard(this.responseText, e);
|
|
122
|
+
}}"
|
|
123
|
+
part="btn btn-outline btn-copy"
|
|
124
|
+
>
|
|
125
|
+
Copy
|
|
126
|
+
</button>
|
|
127
|
+
<pre style="white-space:pre; min-height:50px; height:var(--resp-area-height); resize:vertical; overflow:auto">
|
|
128
|
+
${responseContent}</pre>
|
|
129
|
+
</div>`
|
|
130
|
+
}
|
|
131
|
+
<div
|
|
132
|
+
part="tab-content"
|
|
133
|
+
class="tab-content col m-markdown"
|
|
134
|
+
style="flex:1; display:${this.activeResponseTab === "headers" ? "flex" : "none"};"
|
|
135
|
+
>
|
|
136
|
+
<button
|
|
137
|
+
class="btn btn-sm btn-outline toolbar-btn"
|
|
138
|
+
@click="${(e) => {
|
|
139
|
+
copyToClipboard(this.responseHeaders, e);
|
|
140
|
+
}}"
|
|
141
|
+
part="btn btn-outline btn-copy"
|
|
142
|
+
>
|
|
143
|
+
Copy
|
|
144
|
+
</button>
|
|
145
|
+
<pre style="white-space:pre"><code class="language-css">${this.responseHeaders}</code></pre>
|
|
146
|
+
</div>
|
|
147
|
+
${this.showCurlBeforeTry === "true" ? "" : curlSyntaxTemplate.call(this, this.activeResponseTab === "curl" ? "flex" : "none")}
|
|
148
|
+
</div>`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function apiCallTemplate() {
|
|
152
|
+
let authHtml;
|
|
153
|
+
if (this.security?.length > 0 && !this.security.every((s) => !s || Object.keys(s).length === 0)) {
|
|
154
|
+
if (this.api_keys.length > 0) {
|
|
155
|
+
authHtml = html`<span class="blue-text">
|
|
156
|
+
${this.api_keys.length === 1 ? `${this.api_keys[0]?.typeDisplay} in ${this.api_keys[0].in}` : `${this.api_keys.length} API keys applied`}
|
|
157
|
+
</span>`;
|
|
158
|
+
} else if (this.security.some((s) => !s || Object.keys(s).length === 0)) {
|
|
159
|
+
authHtml = html`Optional (None Applied)`;
|
|
160
|
+
} else {
|
|
161
|
+
authHtml = html`Required <span class="red-text">(None Applied)</span>`;
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
authHtml = html`Not Required`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return html`<div class="try-bar" part="wrap-request-btn">
|
|
168
|
+
<div class="try-layout">
|
|
169
|
+
<dl class="try-info">
|
|
170
|
+
${
|
|
171
|
+
this.serverUrl
|
|
172
|
+
? html`<dt>API Server</dt>
|
|
173
|
+
<dd class="try-server-url">${this.serverUrl}</dd>`
|
|
174
|
+
: ""
|
|
175
|
+
}
|
|
176
|
+
<dt>Authentication</dt>
|
|
177
|
+
<dd>${authHtml}</dd>
|
|
178
|
+
</dl>
|
|
179
|
+
<div class="try-actions">
|
|
180
|
+
${
|
|
181
|
+
this.parameters.length > 0 || this.request_body
|
|
182
|
+
? html` <button
|
|
183
|
+
class="btn btn-outline"
|
|
184
|
+
part="btn btn-outline btn-fill"
|
|
185
|
+
?disabled="${this.loading}"
|
|
186
|
+
@click="${this.onFillRequestData}"
|
|
187
|
+
title="Fills with example data (if provided)"
|
|
188
|
+
>
|
|
189
|
+
FILL EXAMPLE
|
|
190
|
+
</button>
|
|
191
|
+
<button
|
|
192
|
+
class="btn btn-outline"
|
|
193
|
+
part="btn btn-outline btn-clear"
|
|
194
|
+
?disabled="${this.loading}"
|
|
195
|
+
@click="${this.onClearRequestData}"
|
|
196
|
+
>
|
|
197
|
+
CLEAR
|
|
198
|
+
</button>`
|
|
199
|
+
: ""
|
|
200
|
+
}
|
|
201
|
+
<button
|
|
202
|
+
class="btn btn-primary"
|
|
203
|
+
part="btn btn-try"
|
|
204
|
+
?disabled="${this.loading}"
|
|
205
|
+
aria-busy="${this.loading}"
|
|
206
|
+
@click="${this.onTryClick}"
|
|
207
|
+
>
|
|
208
|
+
${this.loading ? "TRYING..." : "TRY"}
|
|
209
|
+
</button>
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
<div class="row" style="font-size:var(--font-size-small); margin:5px 0">
|
|
214
|
+
${this.showCurlBeforeTry === "true" ? curlSyntaxTemplate.call(this) : ""}
|
|
215
|
+
</div>
|
|
216
|
+
${this.responseMessage === "" ? "" : apiResponseTabTemplate.call(this)} `;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export default apiCallTemplate;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders OpenAPI callback requests and nested response definitions within an endpoint.
|
|
3
|
+
*/
|
|
4
|
+
import { html } from "lit";
|
|
5
|
+
|
|
6
|
+
export default function callbackTemplate(callbacks) {
|
|
7
|
+
return html`
|
|
8
|
+
<h4 class="rapidoc-heading label-heading req-res-title" part="heading heading-4">Callbacks</h4>
|
|
9
|
+
${Object.entries(callbacks).map(
|
|
10
|
+
(kv) => html`
|
|
11
|
+
<div class="tiny-title" style="padding: 12px; border:1px solid var(--border)">
|
|
12
|
+
<h5 class="rapidoc-heading callback-name" part="heading heading-5">${kv[0]}</h5>
|
|
13
|
+
${Object.entries(kv[1]).map(
|
|
14
|
+
(pathObj) => html`
|
|
15
|
+
<div class="callback-operation-list mono-font small-font-size">
|
|
16
|
+
${Object.entries(pathObj[1]).map(
|
|
17
|
+
(method) => html`
|
|
18
|
+
<div class="callback-operation-item">
|
|
19
|
+
<div class="callback-operation-header">
|
|
20
|
+
<div class="method method-fg ${method[0]} callback-method">
|
|
21
|
+
<span style="font-size:20px;"> ⥄ </span>
|
|
22
|
+
${method[0]}
|
|
23
|
+
</div>
|
|
24
|
+
<span style="line-height:20px; vertical-align: baseline;">${pathObj[0]}</span>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="expanded-req-resp-container">
|
|
27
|
+
<api-request
|
|
28
|
+
.config="${this.config}"
|
|
29
|
+
class="${this.renderStyle}-mode callback"
|
|
30
|
+
style="width:100%;"
|
|
31
|
+
callback="true"
|
|
32
|
+
method="${method[0] || ""}"
|
|
33
|
+
path="${pathObj[0] || ""}"
|
|
34
|
+
.parameters="${method[1]?.parameters || ""}"
|
|
35
|
+
.request_body="${method[1]?.requestBody || ""}"
|
|
36
|
+
fill-request-fields-with-example="${this.fillRequestFieldsWithExample}"
|
|
37
|
+
allow-try="false"
|
|
38
|
+
render-style="${this.renderStyle}"
|
|
39
|
+
schema-style="${this.schemaStyle}"
|
|
40
|
+
active-schema-tab="${this.defaultSchemaTab}"
|
|
41
|
+
schema-expand-level="${this.schemaExpandLevel}"
|
|
42
|
+
schema-description-expanded="${this.schemaDescriptionExpanded}"
|
|
43
|
+
allow-schema-description-expand-toggle="${this.allowSchemaDescriptionExpandToggle}"
|
|
44
|
+
schema-hide-read-only="false"
|
|
45
|
+
schema-hide-write-only="${this.schemaHideWriteOnly === "never" ? "false" : "true"}"
|
|
46
|
+
fetch-credentials="${this.fetchCredentials}"
|
|
47
|
+
exportparts="section-request-title:section-request-title, heading:heading, heading-4:heading-4, heading-5:heading-5, heading-6:heading-6,
|
|
48
|
+
wrap-request-btn:wrap-request-btn, btn:btn, btn-fill:btn-fill, btn-outline:btn-outline, btn-try:btn-try, btn-clear:btn-clear, btn-clear-resp:btn-clear-resp,
|
|
49
|
+
tab-panel:tab-panel, tab-btn:tab-btn, tab-btn-row:tab-btn-row, tab-content:tab-content,
|
|
50
|
+
file-input:file-input, textbox:textbox, textbox-param:textbox-param, textarea:textarea, textarea-param:textarea-param,
|
|
51
|
+
anchor:anchor, anchor-param-example:anchor-param-example, anchor-param-constraint:anchor-param-constraint, param-list:param-list, param:param, param-label:param-label, param-name:param-name, param-type:param-type, param-input:param-input, param-constraint:param-constraint, param-constraint-label:param-constraint-label, param-details:param-details, param-example-list:param-example-list, value-list:value-list, value-list-label:value-list-label, value-list-items:value-list-items, schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle"
|
|
52
|
+
>
|
|
53
|
+
</api-request>
|
|
54
|
+
|
|
55
|
+
<api-response
|
|
56
|
+
.config="${this.config}"
|
|
57
|
+
style="width:100%;"
|
|
58
|
+
class="${this.renderStyle}-mode"
|
|
59
|
+
callback="true"
|
|
60
|
+
.responses="${method[1]?.responses}"
|
|
61
|
+
render-style="${this.renderStyle}"
|
|
62
|
+
schema-style="${this.schemaStyle}"
|
|
63
|
+
active-schema-tab="${this.defaultSchemaTab}"
|
|
64
|
+
schema-expand-level="${this.schemaExpandLevel}"
|
|
65
|
+
schema-description-expanded="${this.schemaDescriptionExpanded}"
|
|
66
|
+
allow-schema-description-expand-toggle="${this.allowSchemaDescriptionExpandToggle}"
|
|
67
|
+
schema-hide-read-only="${this.schemaHideReadOnly === "never" ? "false" : "true"}"
|
|
68
|
+
schema-hide-write-only="false"
|
|
69
|
+
exportparts="section-response-title:section-response-title, heading:heading, heading-4:heading-4, heading-5:heading-5, heading-6:heading-6,
|
|
70
|
+
btn:btn, btn-response-status:btn-response-status, btn-selected-response-status:btn-selected-response-status, btn-fill:btn-fill, btn-outline:btn-outline, btn-copy:btn-copy,
|
|
71
|
+
tab-panel:tab-panel, tab-btn:tab-btn, tab-btn-row:tab-btn-row, tab-content:tab-content,
|
|
72
|
+
schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle, param-list:param-list, param:param, param-label:param-label, param-name:param-name, param-type:param-type, param-constraint:param-constraint, param-constraint-label:param-constraint-label, param-details:param-details, param-example-list:param-example-list, value-list:value-list, value-list-label:value-list-label, value-list-items:value-list-items"
|
|
73
|
+
>
|
|
74
|
+
</api-response>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
`,
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
`,
|
|
81
|
+
)}
|
|
82
|
+
</div>
|
|
83
|
+
`,
|
|
84
|
+
)}
|
|
85
|
+
`;
|
|
86
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders multi-language code snippets and custom x-codeSamples / x-code-samples tab panels.
|
|
3
|
+
*/
|
|
4
|
+
import { html } from "lit";
|
|
5
|
+
|
|
6
|
+
import { copyToClipboard } from "~/utils/common-utils";
|
|
7
|
+
import { scheduleHighlight } from "~/utils/highlighter";
|
|
8
|
+
|
|
9
|
+
export default function codeSamplesTemplate(xCodeSamples) {
|
|
10
|
+
return html` <div class="code-samples-container">
|
|
11
|
+
<h4 class="rapidoc-heading label-heading table-title top-gap" part="heading heading-4">Code samples</h4>
|
|
12
|
+
<div
|
|
13
|
+
part="tab-panel"
|
|
14
|
+
class="tab-panel col"
|
|
15
|
+
@click="${(e) => {
|
|
16
|
+
if (!e.target.classList.contains("tab-btn")) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const clickedTab = e.target.dataset.tab;
|
|
20
|
+
|
|
21
|
+
const tabButtons = [...e.currentTarget.querySelectorAll(".tab-btn")];
|
|
22
|
+
const tabContents = [...e.currentTarget.querySelectorAll(".tab-content")];
|
|
23
|
+
tabButtons.forEach((tabBtnEl) =>
|
|
24
|
+
tabBtnEl.classList[tabBtnEl.dataset.tab === clickedTab ? "add" : "remove"]("active"),
|
|
25
|
+
);
|
|
26
|
+
tabContents.forEach((tabBodyEl) => {
|
|
27
|
+
tabBodyEl.style.display = tabBodyEl.dataset.tab === clickedTab ? "block" : "none";
|
|
28
|
+
});
|
|
29
|
+
scheduleHighlight(e.currentTarget.getRootNode()?.host?.shadowRoot || e.currentTarget);
|
|
30
|
+
}}"
|
|
31
|
+
>
|
|
32
|
+
<div part="tab-btn-row" class="tab-buttons row" style="width:100%; overflow:auto;">
|
|
33
|
+
${xCodeSamples.map((v, i) => html`<button part="tab-btn" class="tab-btn ${i === 0 ? "active" : ""}" data-tab="${v.lang}${i}">${v.label || v.lang}</button>`)}
|
|
34
|
+
</div>
|
|
35
|
+
${xCodeSamples.map(
|
|
36
|
+
(v, i) =>
|
|
37
|
+
html`<div class="tab-content m-markdown" style="display:${i === 0 ? "block" : "none"}" data-tab="${v.lang}${i}">
|
|
38
|
+
<button
|
|
39
|
+
class="btn btn-sm btn-outline toolbar-btn"
|
|
40
|
+
part="btn btn-outline btn-copy"
|
|
41
|
+
@click="${(e) => {
|
|
42
|
+
copyToClipboard(v.source, e);
|
|
43
|
+
}}"
|
|
44
|
+
>
|
|
45
|
+
Copy
|
|
46
|
+
</button>
|
|
47
|
+
<pre><code class="language-${v.lang?.toLowerCase()}">${v.source}</code></pre>
|
|
48
|
+
</div>`,
|
|
49
|
+
)}
|
|
50
|
+
</div>
|
|
51
|
+
</div>`;
|
|
52
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders reusable OpenAPI component definitions (schemas, models) in the document.
|
|
3
|
+
*/
|
|
4
|
+
import { html } from "lit";
|
|
5
|
+
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
6
|
+
import { sanitizeHTML } from "../utils/sanitize.js";
|
|
7
|
+
import { marked } from "marked";
|
|
8
|
+
import { schemaToAST } from "~/utils/schema-utils";
|
|
9
|
+
import "~/components/json-tree";
|
|
10
|
+
import "~/components/schema-tree";
|
|
11
|
+
import "~/components/schema-table";
|
|
12
|
+
|
|
13
|
+
function schemaBodyTemplate(sComponent) {
|
|
14
|
+
return html` <div class="expanded-endpoint-body observe-me ${sComponent.name}" id="cmp--${sComponent.id}">
|
|
15
|
+
<h3 class="rapidoc-heading component-title" part="heading heading-3">
|
|
16
|
+
${sComponent.name} <span style="color:var(--muted-foreground); font-size:var(--font-size-small); font-weight:400;"> Schema </span>
|
|
17
|
+
</h3>
|
|
18
|
+
${
|
|
19
|
+
this.schemaStyle === "table"
|
|
20
|
+
? html` <schema-table
|
|
21
|
+
.data="${schemaToAST(sComponent.component)}"
|
|
22
|
+
schema-expand-level="${this.schemaExpandLevel}"
|
|
23
|
+
schema-description-expanded="${this.schemaDescriptionExpanded}"
|
|
24
|
+
allow-schema-description-expand-toggle="${this.allowSchemaDescriptionExpandToggle}"
|
|
25
|
+
schema-hide-read-only="false"
|
|
26
|
+
schema-hide-write-only="${this.schemaHideWriteOnly}"
|
|
27
|
+
exportparts="schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle"
|
|
28
|
+
>
|
|
29
|
+
</schema-table>`
|
|
30
|
+
: html`<schema-tree
|
|
31
|
+
.data="${schemaToAST(sComponent.component)}"
|
|
32
|
+
schema-expand-level="${this.schemaExpandLevel}"
|
|
33
|
+
schema-description-expanded="${this.schemaDescriptionExpanded}"
|
|
34
|
+
allow-schema-description-expand-toggle="${this.allowSchemaDescriptionExpandToggle}"
|
|
35
|
+
schema-hide-read-only="false"
|
|
36
|
+
schema-hide-write-only="${this.schemaHideWriteOnly}"
|
|
37
|
+
exportparts="schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle"
|
|
38
|
+
>
|
|
39
|
+
</schema-tree>`
|
|
40
|
+
}
|
|
41
|
+
</div>`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function componentBodyTemplate(sComponent, componentType) {
|
|
45
|
+
if (sComponent.id.indexOf("schemas-") !== -1) {
|
|
46
|
+
return schemaBodyTemplate.call(this, sComponent);
|
|
47
|
+
}
|
|
48
|
+
return html`
|
|
49
|
+
<div class="expanded-endpoint-body observe-me ${sComponent.name}" id="cmp--${sComponent.id}">
|
|
50
|
+
${html`
|
|
51
|
+
<h3 class="rapidoc-heading component-title" part="heading heading-3">
|
|
52
|
+
${sComponent.name}
|
|
53
|
+
<span style="color:var(--muted-foreground); font-size:var(--font-size-small); font-weight:400"> ${componentType} </span>
|
|
54
|
+
</h3>
|
|
55
|
+
${
|
|
56
|
+
sComponent.component
|
|
57
|
+
? html`<div class="mono-font regular-font-size" style="padding: 8px 0; color:var(--card-foreground)">
|
|
58
|
+
<json-tree class="border tree" render-style="${this.renderStyle}" .data="${sComponent.component}"> </json-tree>
|
|
59
|
+
</div>`
|
|
60
|
+
: ""
|
|
61
|
+
}
|
|
62
|
+
`}
|
|
63
|
+
</div>
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default function componentsTemplate() {
|
|
68
|
+
if (!this.resolvedSpec) {
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
return html`
|
|
72
|
+
${this.resolvedSpec.components.map(
|
|
73
|
+
(component) => html`
|
|
74
|
+
<div id="cmp--${component.name.toLowerCase()}" class="regular-font section-gap--read-mode observe-me read-mode-tag">
|
|
75
|
+
<h2 class="rapidoc-heading title tag" part="heading heading-2">${component.name}</h2>
|
|
76
|
+
${unsafeHTML(`<div class='m-markdown regular-font'>${sanitizeHTML(marked(component.description || ""))}</div>`)}
|
|
77
|
+
</div>
|
|
78
|
+
<div class="regular-font section-gap--read-mode">
|
|
79
|
+
${component.subComponents
|
|
80
|
+
.filter((c) => c.expanded !== false)
|
|
81
|
+
.map((sComponent) => componentBodyTemplate.call(this, sComponent, component.name))}
|
|
82
|
+
</div>
|
|
83
|
+
`,
|
|
84
|
+
)}
|
|
85
|
+
`;
|
|
86
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedicated Download & Export Action Bar for OpenAPI specs and curated MCP servers.
|
|
3
|
+
* Rendered independently of show-info to guarantee accessibility across all render modes.
|
|
4
|
+
*/
|
|
5
|
+
import { html } from "lit";
|
|
6
|
+
import { downloadResource, viewResource } from "~/utils/common-utils";
|
|
7
|
+
import { parseMcpTargets, MCP_TARGET_LABELS } from "~/utils/mcp-generator";
|
|
8
|
+
|
|
9
|
+
export default function downloadsTemplate() {
|
|
10
|
+
const mcpTargets = parseMcpTargets(this.mcp);
|
|
11
|
+
const showSpecDownload = this.specUrl && this.allowSpecFileDownload === "true";
|
|
12
|
+
const showMcpExport = mcpTargets.length > 0;
|
|
13
|
+
|
|
14
|
+
if (!showSpecDownload && !showMcpExport) {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let sectionClass = "section-gap";
|
|
19
|
+
if (this.renderStyle === "focused") {
|
|
20
|
+
sectionClass = "section-gap--focused-mode";
|
|
21
|
+
} else if (this.renderStyle === "read") {
|
|
22
|
+
sectionClass = "section-gap--read-mode";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return html`
|
|
26
|
+
<section id="downloads" part="section-downloads" class="downloads-bar observe-me ${sectionClass}">
|
|
27
|
+
${
|
|
28
|
+
showSpecDownload
|
|
29
|
+
? html`
|
|
30
|
+
<button
|
|
31
|
+
class="btn btn-outline download-btn"
|
|
32
|
+
part="btn btn-outline"
|
|
33
|
+
@click="${() => {
|
|
34
|
+
downloadResource(this.specUrl, "openapi-spec");
|
|
35
|
+
}}"
|
|
36
|
+
>
|
|
37
|
+
Download OpenAPI spec
|
|
38
|
+
</button>
|
|
39
|
+
${
|
|
40
|
+
this.specUrl?.trim().toLowerCase().endsWith("json")
|
|
41
|
+
? html`<button
|
|
42
|
+
class="btn btn-outline download-btn view-spec"
|
|
43
|
+
part="btn btn-outline"
|
|
44
|
+
@click="${() => {
|
|
45
|
+
viewResource(this.specUrl);
|
|
46
|
+
}}"
|
|
47
|
+
>
|
|
48
|
+
View OpenAPI spec (New Tab)
|
|
49
|
+
</button>`
|
|
50
|
+
: ""
|
|
51
|
+
}
|
|
52
|
+
`
|
|
53
|
+
: ""
|
|
54
|
+
}
|
|
55
|
+
${
|
|
56
|
+
showMcpExport
|
|
57
|
+
? mcpTargets.length === 1
|
|
58
|
+
? html`<button
|
|
59
|
+
class="btn btn-outline download-btn"
|
|
60
|
+
part="btn btn-outline btn-mcp-export"
|
|
61
|
+
@click="${() => {
|
|
62
|
+
this.downloadMcpServer(mcpTargets[0]);
|
|
63
|
+
}}"
|
|
64
|
+
>
|
|
65
|
+
Export MCP Server (${MCP_TARGET_LABELS[mcpTargets[0]] || mcpTargets[0]})
|
|
66
|
+
</button>`
|
|
67
|
+
: html`<select
|
|
68
|
+
class="btn btn-outline download-select"
|
|
69
|
+
part="btn btn-outline btn-mcp-export"
|
|
70
|
+
@change="${(e) => {
|
|
71
|
+
const target = e.target.value;
|
|
72
|
+
if (target) {
|
|
73
|
+
this.downloadMcpServer(target);
|
|
74
|
+
e.target.value = "";
|
|
75
|
+
}
|
|
76
|
+
}}"
|
|
77
|
+
>
|
|
78
|
+
<option value="" disabled selected>Export MCP Server</option>
|
|
79
|
+
${mcpTargets.map((t) => html`<option value="${t}">Export ${MCP_TARGET_LABELS[t] || t}</option>`)}
|
|
80
|
+
</select>`
|
|
81
|
+
: ""
|
|
82
|
+
}
|
|
83
|
+
</section>
|
|
84
|
+
`;
|
|
85
|
+
}
|