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.
Files changed (80) hide show
  1. package/README.md +46 -31
  2. package/dist/rapidoc-min.js +1424 -213
  3. package/dist/rapidoc-static-min.js +13542 -0
  4. package/package.json +48 -34
  5. package/src/components/api-request.ts +869 -0
  6. package/src/components/api-response.ts +509 -0
  7. package/src/components/json-tree.ts +171 -0
  8. package/src/components/schema-base-element.ts +315 -0
  9. package/src/components/schema-table.ts +430 -0
  10. package/src/components/schema-tree.ts +386 -0
  11. package/src/components/tag-input.ts +184 -0
  12. package/src/index.js +6 -0
  13. package/src/oauth-receiver.ts +29 -0
  14. package/src/rapidoc-mini.ts +582 -0
  15. package/src/rapidoc.ts +1808 -0
  16. package/src/static/index.d.ts +149 -0
  17. package/src/static/index.js +62 -0
  18. package/src/static/navigation.js +497 -0
  19. package/src/static/render.js +490 -0
  20. package/src/static/serializer.js +216 -0
  21. package/src/styles/auth-styles.js +318 -0
  22. package/src/styles/border-styles.js +24 -0
  23. package/src/styles/css-bundle.js +129 -0
  24. package/src/styles/custom-styles.js +8 -0
  25. package/src/styles/dialog-box-styles.js +102 -0
  26. package/src/styles/endpoint-styles.js +559 -0
  27. package/src/styles/flex-styles.js +16 -0
  28. package/src/styles/font-styles.js +432 -0
  29. package/src/styles/info-styles.js +36 -0
  30. package/src/styles/input-styles.js +555 -0
  31. package/src/styles/layout-styles.js +396 -0
  32. package/src/styles/microlighter-styles.js +99 -0
  33. package/src/styles/nav-styles.js +609 -0
  34. package/src/styles/param-list-styles.js +261 -0
  35. package/src/styles/schema-styles.js +288 -0
  36. package/src/styles/tab-styles.js +106 -0
  37. package/src/styles/theme-tokens.js +582 -0
  38. package/src/templates/advanced-search-dialog-template.js +94 -0
  39. package/src/templates/api-response-template.js +219 -0
  40. package/src/templates/callback-template.js +86 -0
  41. package/src/templates/code-samples-template.js +52 -0
  42. package/src/templates/components-template.js +86 -0
  43. package/src/templates/downloads-template.js +85 -0
  44. package/src/templates/endpoint-template.js +386 -0
  45. package/src/templates/expanded-endpoint-template.js +266 -0
  46. package/src/templates/focused-endpoint-template.js +145 -0
  47. package/src/templates/header-template.js +92 -0
  48. package/src/templates/logo-template.js +21 -0
  49. package/src/templates/main-body-template.js +102 -0
  50. package/src/templates/navbar-template.js +489 -0
  51. package/src/templates/overview-template.js +104 -0
  52. package/src/templates/request-body-template.js +651 -0
  53. package/src/templates/request-params-template.js +474 -0
  54. package/src/templates/security-scheme-template.js +1263 -0
  55. package/src/templates/server-template.js +152 -0
  56. package/src/utils/auto-color-scheme.js +99 -0
  57. package/src/utils/bind-navbar.js +175 -0
  58. package/src/utils/color-utils.js +59 -0
  59. package/src/utils/common-utils.js +191 -0
  60. package/src/utils/curl-utils.js +123 -0
  61. package/src/utils/highlighter.js +416 -0
  62. package/src/utils/markdown-utils.js +110 -0
  63. package/src/utils/mcp/common.js +467 -0
  64. package/src/utils/mcp/generators/csharp.js +242 -0
  65. package/src/utils/mcp/generators/go.js +298 -0
  66. package/src/utils/mcp/generators/java.js +330 -0
  67. package/src/utils/mcp/generators/python.js +248 -0
  68. package/src/utils/mcp/generators/rust.js +281 -0
  69. package/src/utils/mcp/generators/typescript.js +290 -0
  70. package/src/utils/mcp-generator.js +143 -0
  71. package/src/utils/mock-interceptor.js +508 -0
  72. package/src/utils/oauth-utils.js +87 -0
  73. package/src/utils/request-utils.js +203 -0
  74. package/src/utils/response-utils.js +203 -0
  75. package/src/utils/sanitize.js +57 -0
  76. package/src/utils/schema-utils.js +1927 -0
  77. package/src/utils/slugger.js +189 -0
  78. package/src/utils/spec-parser.js +915 -0
  79. package/src/utils/url-utils.js +211 -0
  80. package/src/utils/xml-utils.js +61 -0
@@ -0,0 +1,474 @@
1
+ /**
2
+ * Renders path, query, header, and cookie parameter inputs, schema tree previews, constraints, and clickable example badges for <api-request>.
3
+ */
4
+ import { html } from "lit";
5
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
6
+ import { live } from "lit/directives/live.js";
7
+ import { sanitizeHTML } from "../utils/sanitize.js";
8
+ import { marked } from "marked";
9
+ import {
10
+ schemaToAST,
11
+ getTypeInfo,
12
+ normalizeExamples,
13
+ getSchemaFromParam,
14
+ generateExample,
15
+ standardizeExample,
16
+ anyExampleWithSummaryOrDescription,
17
+ EMPTY_ARRAY,
18
+ } from "~/utils/schema-utils";
19
+ import "~/components/schema-tree";
20
+ import "~/components/tag-input";
21
+
22
+ /**
23
+ * A label followed by a wrapping list of values (Allowed values, Examples).
24
+ * Wrapped lines hang under the first value; CSS draws the separators.
25
+ */
26
+ export function valueListTemplate(label, items) {
27
+ return html`<div class="value-list" part="value-list">
28
+ <span class="param-constraint-label value-list-label" part="value-list-label">${label}</span>
29
+ <ul class="value-list-items" part="value-list-items" role="list">
30
+ ${items.map((item) => html`<li>${item}</li>`)}
31
+ </ul>
32
+ </div>`;
33
+ }
34
+
35
+ /**
36
+ * Constraints as label/value pairs. The labels share one column, so every value starts at the same place,
37
+ * whether there is one constraint or several. Limits (range, multiple of, length) and allowed values wrap
38
+ * as value lists, hanging under their first value.
39
+ */
40
+ export function constraintListTemplate(paramSchema, allowedItems, exampleItems) {
41
+ const valueItems = (items) =>
42
+ html`<ul class="value-list-items" part="value-list-items" role="list">
43
+ ${items.map((item) => html`<li>${item}</li>`)}
44
+ </ul>`;
45
+ const row = (label, value) =>
46
+ html`<dt class="param-constraint-label" part="param-constraint-label">${label}</dt>
47
+ <dd>${value}</dd>`;
48
+ return html`<dl class="param-constraint" part="param-constraint">
49
+ ${paramSchema.default ? row("Default:", paramSchema.default) : ""} ${paramSchema.pattern ? row("Pattern:", paramSchema.pattern) : ""}
50
+ ${
51
+ paramSchema.constrain
52
+ ? row(
53
+ "Limits:",
54
+ valueItems(
55
+ paramSchema.constrain
56
+ .split("┃")
57
+ .map((v) => v.trim())
58
+ .filter(Boolean),
59
+ ),
60
+ )
61
+ : ""
62
+ }
63
+ ${allowedItems ? row("Allowed:", valueItems(allowedItems)) : ""} ${exampleItems ? row("Examples:", valueItems(exampleItems)) : ""}
64
+ </dl>`;
65
+ }
66
+
67
+ /**
68
+ * Short examples join the constraint list (lined up with the other values) when there is no description to put them under.
69
+ * Long-format examples, with a summary or description, always stay in the details.
70
+ */
71
+ export function examplesBesideConstraints(description, hasConstraint, exampleList = []) {
72
+ return (
73
+ !description?.trim() &&
74
+ Boolean(hasConstraint) &&
75
+ exampleList.length > 0 &&
76
+ !anyExampleWithSummaryOrDescription(exampleList)
77
+ );
78
+ }
79
+
80
+ export function renderExample(example, paramType, paramName) {
81
+ return html`
82
+ ${paramType === "array" ? "[" : ""}
83
+ <button
84
+ type="button"
85
+ part="anchor anchor-param-example"
86
+ class="value-chip"
87
+ ?disabled="${this.allowTry !== "true"}"
88
+ data-example-type="${paramType === "array" ? paramType : "string"}"
89
+ data-example="${
90
+ example.value && Array.isArray(example.value)
91
+ ? example.value?.join("~|~")
92
+ : (typeof example.value === "object"
93
+ ? JSON.stringify(example.value, null, 2)
94
+ : example.value) || ""
95
+ }"
96
+ title="${
97
+ example.value && Array.isArray(example.value)
98
+ ? example.value?.join("~|~")
99
+ : (typeof example.value === "object"
100
+ ? JSON.stringify(example.value, null, 2)
101
+ : example.value) || ""
102
+ }"
103
+ @click="${(e) => {
104
+ const inputEl = e.target
105
+ .closest(".param-list")
106
+ .querySelector(`[data-pname="${paramName}"]`);
107
+ if (inputEl) {
108
+ inputEl.value =
109
+ e.target.dataset.exampleType === "array"
110
+ ? e.target.dataset.example.split("~|~")
111
+ : e.target.dataset.example;
112
+ }
113
+ }}"
114
+ >
115
+ ${example.printableValue || example.value}
116
+ </button>
117
+ ${paramType === "array" ? "] " : ""}
118
+ `;
119
+ }
120
+
121
+ export function renderShortFormatExamples(examples, paramType, paramName) {
122
+ return valueListTemplate(
123
+ "Examples:",
124
+ examples.map((x) => renderExample.call(this, x, paramType, paramName)),
125
+ );
126
+ }
127
+
128
+ export function renderLongFormatExamples(exampleList, paramType, paramName) {
129
+ return html` <ul class="param-example-list" part="param-example-list" role="list">
130
+ ${exampleList.map(
131
+ (v) =>
132
+ html`<li>
133
+ ${renderExample.call(this, v, paramType, paramName)} ${v.summary?.length > 0 ? html`<span>&lpar;${v.summary}&rpar;</span>` : ""}
134
+ ${v.description?.length > 0 ? html`<div class="m-markdown-small">${unsafeHTML(sanitizeHTML(marked(v.description)))}</div>` : ""}
135
+ </li>`,
136
+ )}
137
+ </ul>`;
138
+ }
139
+
140
+ export function exampleListTemplate(paramName, paramType, exampleList = []) {
141
+ return html` ${
142
+ exampleList.length > 0
143
+ ? anyExampleWithSummaryOrDescription(exampleList)
144
+ ? html`<span class="param-constraint-label">Examples: </span>
145
+ ${renderLongFormatExamples.call(this, exampleList, paramType, paramName)}`
146
+ : renderShortFormatExamples.call(this, exampleList, paramType, paramName)
147
+ : ""
148
+ }`;
149
+ }
150
+
151
+ export function inputParametersTemplate(paramType) {
152
+ const filteredParams = this.parameters
153
+ ? this.parameters.filter((param) => param.in === paramType)
154
+ : [];
155
+ if (filteredParams.length === 0) {
156
+ return "";
157
+ }
158
+ let title = "";
159
+ if (paramType === "path") {
160
+ title = "Path parameters";
161
+ } else if (paramType === "query") {
162
+ title = "Query-string parameters";
163
+ } else if (paramType === "header") {
164
+ title = "Request headers";
165
+ } else if (paramType === "cookie") {
166
+ title = "Cookies";
167
+ }
168
+
169
+ const paramItems = [];
170
+ for (const param of filteredParams) {
171
+ const [declaredParamSchema, serializeStyle, mimeTypeElem] = getSchemaFromParam(param);
172
+ if (!declaredParamSchema) {
173
+ continue;
174
+ }
175
+ const paramSchema = getTypeInfo(declaredParamSchema);
176
+ if (!paramSchema) {
177
+ continue;
178
+ }
179
+ const schemaAsObj = schemaToAST(declaredParamSchema);
180
+ let paramStyle = "form";
181
+ let paramExplode = true;
182
+ let paramAllowReserved = false;
183
+ if (paramType === "query" || paramType === "header" || paramType === "path") {
184
+ if (param.style && "form spaceDelimited pipeDelimited".includes(param.style)) {
185
+ paramStyle = param.style;
186
+ } else if (serializeStyle) {
187
+ paramStyle = serializeStyle;
188
+ }
189
+ if (typeof param.explode === "boolean") {
190
+ paramExplode = param.explode;
191
+ }
192
+ if (typeof param.allowReserved === "boolean") {
193
+ paramAllowReserved = param.allowReserved;
194
+ }
195
+ }
196
+ // openapi 3.1.0 spec based examples (which must be Object(string : { value:any, summary?: string, description?: string})
197
+ const example = normalizeExamples(
198
+ standardizeExample(param.examples) ||
199
+ standardizeExample(param.example) ||
200
+ standardizeExample(mimeTypeElem?.example) ||
201
+ standardizeExample(mimeTypeElem?.examples) ||
202
+ standardizeExample(paramSchema.examples) ||
203
+ standardizeExample(paramSchema.example),
204
+ paramSchema.type,
205
+ );
206
+ if (
207
+ !example.exampleVal &&
208
+ (paramSchema.type === "object" || paramSchema.type.split("┃").includes("object"))
209
+ ) {
210
+ example.exampleVal =
211
+ generateExample(
212
+ declaredParamSchema,
213
+ serializeStyle || "json",
214
+ {},
215
+ {},
216
+ this.callback === "true" || this.webhook === "true" ? true : false,
217
+ this.callback === "true" || this.webhook === "true" ? false : true,
218
+ "text",
219
+ false,
220
+ )[0]?.exampleValue || "";
221
+ }
222
+ const hasConstraint =
223
+ paramSchema.default ||
224
+ paramSchema.constrain ||
225
+ paramSchema.allowedValues ||
226
+ paramSchema.pattern;
227
+ const inlineExamples = examplesBesideConstraints(
228
+ param.description,
229
+ hasConstraint,
230
+ example.exampleList,
231
+ );
232
+ paramItems.push(html`
233
+ <li class="param ${param.deprecated ? "deprecated" : ""}" part="param" title="${param.deprecated ? "Deprecated" : ""}">
234
+ <div class="param-label" part="param-label">
235
+ <div class="param-name ${param.deprecated ? "deprecated" : ""}" part="param-name">
236
+ ${
237
+ param.deprecated
238
+ ? html`<svg class="param-deprecated-icon" viewBox="0 0 10 10" width="10" height="10" aria-hidden="true">
239
+ <path d="M2 2L8 8M2 8L8 2" />
240
+ </svg>`
241
+ : ""
242
+ }
243
+ ${param.required ? html`<span class="param-required" title="Required">*</span>` : ""} ${param.name}
244
+ </div>
245
+ <div class="param-type" part="param-type">
246
+ ${
247
+ paramSchema.type === "array" || paramSchema.type.split("┃").includes("array")
248
+ ? `${paramSchema.arrayType || paramSchema.type}`
249
+ : `${paramSchema.format && !paramSchema.type.includes("┃") ? paramSchema.format : paramSchema.contentMediaType && !paramSchema.type.includes("┃") ? paramSchema.contentMediaType : paramSchema.type}`
250
+ }
251
+ </div>
252
+ </div>
253
+ ${
254
+ this.allowTry === "true"
255
+ ? html` <div class="param-input" part="param-input">
256
+ ${
257
+ paramSchema.type === "array" ||
258
+ (paramSchema.type.split("┃").includes("array") &&
259
+ !paramSchema.type.split("┃").includes("object"))
260
+ ? html`<tag-input
261
+ class="request-param"
262
+ id="tag-input-request-param-${param.name}"
263
+ style="width:100%"
264
+ data-ptype="${paramType}"
265
+ data-pname="${param.name}"
266
+ data-example="${Array.isArray(example.exampleVal) ? example.exampleVal.join("~|~") : example.exampleVal}"
267
+ data-param-serialize-style="${paramStyle}"
268
+ data-param-serialize-explode="${paramExplode}"
269
+ data-param-allow-reserved="${paramAllowReserved}"
270
+ data-x-fill-example="${param["x-fill-example"] || "yes"}"
271
+ data-array="true"
272
+ placeholder="add-multiple &#x21a9;"
273
+ .value="${
274
+ param["x-fill-example"] === "no"
275
+ ? EMPTY_ARRAY
276
+ : live(
277
+ this.fillRequestFieldsWithExample === "true"
278
+ ? Array.isArray(example.exampleVal)
279
+ ? example.exampleVal
280
+ : [example.exampleVal]
281
+ : EMPTY_ARRAY,
282
+ )
283
+ }"
284
+ @input="${(e) => {
285
+ const requestPanelEl = this.getRequestPanel(e);
286
+ this.liveCURLSyntaxUpdate(requestPanelEl);
287
+ }}"
288
+ @change="${(e) => {
289
+ const requestPanelEl = this.getRequestPanel(e);
290
+ this.liveCURLSyntaxUpdate(requestPanelEl);
291
+ }}"
292
+ >
293
+ </tag-input>`
294
+ : paramSchema.type === "object" ||
295
+ paramSchema.type.split("┃").includes("object")
296
+ ? html`<div part="tab-panel" class="tab-panel col">
297
+ <div
298
+ part="tab-btn-row"
299
+ class="tab-buttons row"
300
+ @click="${(e) => {
301
+ if (e.target.tagName.toLowerCase() === "button") {
302
+ const newState = { ...this.activeParameterSchemaTabs };
303
+ newState[param.name] = e.target.dataset.tab;
304
+ this.activeParameterSchemaTabs = newState;
305
+ }
306
+ }}"
307
+ >
308
+ <button
309
+ part="tab-btn"
310
+ class="tab-btn ${this.activeParameterSchemaTabs[param.name] === "example" ? "active" : ""}"
311
+ data-tab="example"
312
+ >
313
+ EXAMPLE
314
+ </button>
315
+ <button
316
+ part="tab-btn"
317
+ class="tab-btn ${this.activeParameterSchemaTabs[param.name] !== "example" ? "active" : ""}"
318
+ data-tab="schema"
319
+ >
320
+ SCHEMA
321
+ </button>
322
+ </div>
323
+
324
+ ${html`<div
325
+ part="tab-content"
326
+ class="tab-content col"
327
+ data-tab="example"
328
+ style="display:${
329
+ this.activeParameterSchemaTabs[param.name] === "example"
330
+ ? "block"
331
+ : "none"
332
+ }; padding-left:5px; width:100%"
333
+ >
334
+ <textarea
335
+ id="textarea-request-param-${param.name}"
336
+ class="textarea request-param"
337
+ part="textarea textarea-param"
338
+ data-ptype="${paramType}-object"
339
+ data-pname="${param.name}"
340
+ data-example="${example.exampleVal}"
341
+ data-param-serialize-style="${paramStyle}"
342
+ data-param-serialize-explode="${paramExplode}"
343
+ data-param-allow-reserved="${paramAllowReserved}"
344
+ data-x-fill-example="${param["x-fill-example"] || "yes"}"
345
+ spellcheck="false"
346
+ .value="${
347
+ param["x-fill-example"] === "no"
348
+ ? ""
349
+ : live(
350
+ this.fillRequestFieldsWithExample === "true"
351
+ ? typeof example.exampleVal === "object"
352
+ ? JSON.stringify(example.exampleVal, null, 2)
353
+ : example.exampleVal
354
+ : "",
355
+ )
356
+ }"
357
+ style="resize:vertical; width:100%; height: ${"read focused".includes(this.renderStyle) ? "180px" : "120px"};"
358
+ @input=${(e) => {
359
+ const requestPanelEl = this.getRequestPanel(e);
360
+ this.liveCURLSyntaxUpdate(requestPanelEl);
361
+ }}
362
+ ></textarea>
363
+ </div>`}
364
+ ${html`<div
365
+ part="tab-content"
366
+ class="tab-content col"
367
+ data-tab="schema"
368
+ style="display:${
369
+ this.activeParameterSchemaTabs[param.name] !== "example"
370
+ ? "block"
371
+ : "none"
372
+ }; padding-left:5px; width:100%;"
373
+ >
374
+ <schema-tree
375
+ class="json"
376
+ style="display: block"
377
+ .data="${schemaAsObj}"
378
+ schema-expand-level="${this.schemaExpandLevel}"
379
+ schema-description-expanded="${this.schemaDescriptionExpanded}"
380
+ allow-schema-description-expand-toggle="${this.allowSchemaDescriptionExpandToggle}"
381
+ schema-hide-read-only="${this.schemaHideReadOnly.includes(this.method)}"
382
+ schema-hide-write-only="${this.schemaHideWriteOnly.includes(this.method)}"
383
+ exportparts="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,
384
+ file-input:file-input, textbox:textbox, textbox-param:textbox-param, textarea:textarea, textarea-param:textarea-param,
385
+ anchor:anchor, anchor-param-example:anchor-param-example"
386
+ >
387
+ </schema-tree>
388
+ </div>`}
389
+ </div>`
390
+ : html` <input
391
+ type="${paramSchema.format === "password" ? "password" : "text"}"
392
+ spellcheck="false"
393
+ style="width:100%"
394
+ id="input-request-param-${param.name}"
395
+ class="request-param"
396
+ part="textbox textbox-param"
397
+ data-ptype="${paramType}"
398
+ data-pname="${param.name}"
399
+ data-example="${Array.isArray(example.exampleVal) ? example.exampleVal.join("~|~") : example.exampleVal}"
400
+ data-param-allow-reserved="${paramAllowReserved}"
401
+ data-x-fill-example="${param["x-fill-example"] || "yes"}"
402
+ data-array="false"
403
+ .value="${
404
+ param["x-fill-example"] === "no"
405
+ ? ""
406
+ : live(
407
+ this.fillRequestFieldsWithExample === "true"
408
+ ? example.exampleVal
409
+ : "",
410
+ )
411
+ }"
412
+ @input=${(e) => {
413
+ const requestPanelEl = this.getRequestPanel(e);
414
+ this.liveCURLSyntaxUpdate(requestPanelEl);
415
+ }}
416
+ />`
417
+ }
418
+ </div>`
419
+ : ""
420
+ }
421
+ ${
422
+ hasConstraint
423
+ ? constraintListTemplate(
424
+ paramSchema,
425
+ paramSchema.allowedValues &&
426
+ String(paramSchema.allowedValues)
427
+ .split("┃")
428
+ .map(
429
+ (v) =>
430
+ html`<button
431
+ type="button"
432
+ part="anchor anchor-param-constraint"
433
+ class="value-chip"
434
+ ?disabled="${this.allowTry !== "true"}"
435
+ data-type="${paramSchema.type === "array" ? paramSchema.type : "string"}"
436
+ data-enum="${v.trim()}"
437
+ @click="${(e) => {
438
+ const inputEl = e.target
439
+ .closest(".param-list")
440
+ .querySelector(`[data-pname="${param.name}"]`);
441
+ if (inputEl) {
442
+ if (e.target.dataset.type === "array") {
443
+ inputEl.value = [e.target.dataset.enum];
444
+ } else {
445
+ inputEl.value = e.target.dataset.enum;
446
+ }
447
+ }
448
+ }}"
449
+ >
450
+ ${v}
451
+ </button>`,
452
+ ),
453
+ inlineExamples &&
454
+ example.exampleList.map((x) =>
455
+ renderExample.call(this, x, paramSchema.type, param.name),
456
+ ),
457
+ )
458
+ : ""
459
+ }
460
+ <div class="param-details" part="param-details">
461
+ ${param.description ? html`<div class="m-markdown-small">${unsafeHTML(sanitizeHTML(marked(param.description)))}</div>` : ""}
462
+ ${inlineExamples ? "" : exampleListTemplate.call(this, param.name, paramSchema.type, example.exampleList)}
463
+ </div>
464
+ </li>
465
+ `);
466
+ }
467
+
468
+ return html` <h5 class="rapidoc-heading label-heading table-title top-gap" part="heading heading-5">${title}</h5>
469
+ <div class="param-list-container">
470
+ <ul class="param-list" part="param-list" role="list">
471
+ ${paramItems}
472
+ </ul>
473
+ </div>`;
474
+ }