rapidoc 11.0.1 → 12.1.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 (96) hide show
  1. package/README.md +171 -54
  2. package/dist/rapidoc-flow-min.js +580 -0
  3. package/dist/rapidoc-flow-min.js.LICENSE.txt +171 -0
  4. package/dist/rapidoc-min.js +645 -202
  5. package/dist/rapidoc-min.js.LICENSE.txt +381 -0
  6. package/package.json +57 -42
  7. package/src/README.md +150 -0
  8. package/src/components/README.md +91 -0
  9. package/src/components/api-request.ts +912 -0
  10. package/src/components/api-response.ts +514 -0
  11. package/src/components/json-tree.ts +171 -0
  12. package/src/components/schema-base-element.ts +329 -0
  13. package/src/components/schema-table.ts +475 -0
  14. package/src/components/schema-tree.ts +393 -0
  15. package/src/components/tag-input.ts +180 -0
  16. package/src/flow.js +3 -0
  17. package/src/index.js +6 -0
  18. package/src/oauth-receiver.ts +29 -0
  19. package/src/rapi-flow.ts +1178 -0
  20. package/src/rapidoc-mini.ts +603 -0
  21. package/src/rapidoc.ts +1854 -0
  22. package/src/styles/README.md +96 -0
  23. package/src/styles/auth-styles.js +318 -0
  24. package/src/styles/border-styles.js +24 -0
  25. package/src/styles/css-bundle.js +129 -0
  26. package/src/styles/custom-styles.js +8 -0
  27. package/src/styles/dialog-box-styles.js +102 -0
  28. package/src/styles/endpoint-styles.js +564 -0
  29. package/src/styles/flex-styles.js +16 -0
  30. package/src/styles/flow-styles.js +248 -0
  31. package/src/styles/font-styles.js +432 -0
  32. package/src/styles/info-styles.js +36 -0
  33. package/src/styles/input-styles.js +555 -0
  34. package/src/styles/layout-styles.js +396 -0
  35. package/src/styles/microlighter-styles.js +99 -0
  36. package/src/styles/nav-styles.js +633 -0
  37. package/src/styles/param-list-styles.js +261 -0
  38. package/src/styles/schema-styles.js +296 -0
  39. package/src/styles/tab-styles.js +106 -0
  40. package/src/styles/theme-tokens.js +582 -0
  41. package/src/templates/README.md +89 -0
  42. package/src/templates/advanced-search-dialog-template.js +94 -0
  43. package/src/templates/api-response-template.js +223 -0
  44. package/src/templates/callback-template.js +86 -0
  45. package/src/templates/code-samples-template.js +52 -0
  46. package/src/templates/components-template.js +86 -0
  47. package/src/templates/downloads-template.js +70 -0
  48. package/src/templates/endpoint-template.js +377 -0
  49. package/src/templates/expanded-endpoint-template.js +270 -0
  50. package/src/templates/focused-endpoint-template.js +146 -0
  51. package/src/templates/header-template.js +92 -0
  52. package/src/templates/logo-template.js +21 -0
  53. package/src/templates/main-body-template.js +102 -0
  54. package/src/templates/navbar-template.js +498 -0
  55. package/src/templates/overview-template.js +104 -0
  56. package/src/templates/request-body-template.js +673 -0
  57. package/src/templates/request-params-template.js +485 -0
  58. package/src/templates/security-scheme-template.js +1272 -0
  59. package/src/templates/server-template.js +153 -0
  60. package/src/utils/README.md +146 -0
  61. package/src/utils/arazzo/README.md +119 -0
  62. package/src/utils/arazzo/components.js +15 -0
  63. package/src/utils/arazzo/graph.js +269 -0
  64. package/src/utils/arazzo/index.js +52 -0
  65. package/src/utils/arazzo/operations.js +106 -0
  66. package/src/utils/arazzo/parse.js +196 -0
  67. package/src/utils/arazzo/refs.js +40 -0
  68. package/src/utils/arazzo/svg.js +707 -0
  69. package/src/utils/auto-color-scheme.js +99 -0
  70. package/src/utils/bind-navbar.js +175 -0
  71. package/src/utils/color-utils.js +59 -0
  72. package/src/utils/common-utils.js +191 -0
  73. package/src/utils/curl-utils.js +126 -0
  74. package/src/utils/highlighter.js +419 -0
  75. package/src/utils/markdown-utils.js +110 -0
  76. package/src/utils/mcp/README.md +155 -0
  77. package/src/utils/mcp/common.js +166 -0
  78. package/src/utils/mcp/manifest.js +382 -0
  79. package/src/utils/mcp/project/server.ts +53 -0
  80. package/src/utils/mcp/project.js +88 -0
  81. package/src/utils/mcp/runtime.js +289 -0
  82. package/src/utils/mcp/schema.js +98 -0
  83. package/src/utils/mcp/workflow-runtime.js +374 -0
  84. package/src/utils/mcp/workflows.js +240 -0
  85. package/src/utils/mcp/zip.js +102 -0
  86. package/src/utils/mcp-generator.js +47 -0
  87. package/src/utils/mock-interceptor.js +557 -0
  88. package/src/utils/oauth-utils.js +87 -0
  89. package/src/utils/request-utils.js +264 -0
  90. package/src/utils/response-utils.js +203 -0
  91. package/src/utils/sanitize.js +57 -0
  92. package/src/utils/schema-utils.js +1954 -0
  93. package/src/utils/slugger.js +187 -0
  94. package/src/utils/spec-parser.js +941 -0
  95. package/src/utils/url-utils.js +246 -0
  96. package/src/utils/xml-utils.js +61 -0
@@ -0,0 +1,329 @@
1
+ import { LitElement, html } from "lit";
2
+ import { property } from "lit/decorators.js";
3
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
4
+ import { marked } from "marked";
5
+ import { sanitizeHTML } from "../utils/sanitize.js";
6
+ import { blockSummary, firstLineHtml } from "../utils/markdown-utils.js";
7
+
8
+ // Markdown or HTML syntax, a bare URL or e-mail (GFM autolinks), or a list, quote, heading or rule marker at the start
9
+ const MARKDOWN_SYNTAX = /[*_`~[\]<>#|\\&\n]|https?:|ftp:|www\.|@|^([-+]|\d+[.)])\s|^-{3,}$/;
10
+
11
+ function isPlainText(text) {
12
+ return !MARKDOWN_SYNTAX.test(text);
13
+ }
14
+
15
+ // Rendered markdown descriptions by source text: large specs repeat the same description thousands of times
16
+ const markdownCache = new Map();
17
+ const MARKDOWN_CACHE_SIZE = 5000;
18
+
19
+ /**
20
+ * Markdown description as sanitized HTML, with the one-line summary and whether the row hides content (see renderDescrCell).
21
+ * @param {string} text - Markdown description, trimmed
22
+ * @param {string} title - Schema title, shown in bold before the description
23
+ * @returns {{ summary: string, html: string, hasMore: boolean }}
24
+ */
25
+ function renderMarkdownDescription(text, title) {
26
+ const key = `${title}\n\n${text}`;
27
+ let rendered = markdownCache.get(key);
28
+ if (rendered) {
29
+ return rendered;
30
+ }
31
+ const firstBlock: any = text ? marked.lexer(text).find((t: any) => t.type !== "space") : null;
32
+ const blockLine = blockSummary(firstBlock);
33
+ // A title can only be prefixed inline to a paragraph; before a list, heading, table, ... it gets its own paragraph
34
+ const titleHtml = title ? `<b>${title}${text ? ":" : ""}</b>` : "";
35
+ const titleOwnBlock = !!titleHtml && !!firstBlock && firstBlock.type !== "paragraph";
36
+ const summary = titleOwnBlock
37
+ ? `${titleHtml} ${blockLine || firstLineHtml(firstBlock)}`
38
+ : blockLine;
39
+ const markdown =
40
+ titleHtml && text ? `${titleHtml}${titleOwnBlock ? "\n\n" : " "}${text}` : titleHtml || text;
41
+ const tokens = markdown ? marked.lexer(markdown) : [];
42
+ const blocks = tokens.filter((t: any) => t.type !== "space");
43
+ rendered = {
44
+ summary: summary ? sanitizeHTML(summary) : "",
45
+ html: blocks.length ? sanitizeHTML(marked.parser(tokens)).trim() : "",
46
+ hasMore:
47
+ !!summary ||
48
+ blocks.length > 1 ||
49
+ (blocks[0]?.type === "list" && blocks[0].items.length > 1) ||
50
+ /<br\s*\/?>(?!\s*$)/i.test(markdown),
51
+ };
52
+ if (markdownCache.size >= MARKDOWN_CACHE_SIZE) {
53
+ markdownCache.clear();
54
+ }
55
+ markdownCache.set(key, rendered);
56
+ return rendered;
57
+ }
58
+
59
+ /**
60
+ * The host's `schema-hide-*` flags are `"default"` | `"never"`: `"never"` shows the fields, `"default"` keeps
61
+ * the `"true"` | `"false"` the template chose for this element (requests hide read-only, responses write-only).
62
+ */
63
+ function hideFlagFromConfig(configValue, current) {
64
+ if (configValue === "never") return "false";
65
+ if (configValue === "true" || configValue === "false") return configValue;
66
+ return current;
67
+ }
68
+
69
+ export default class SchemaBaseElement extends LitElement {
70
+ @property({ type: Object }) config: any;
71
+ @property({ type: Object }) data: any;
72
+ @property({ type: Number, attribute: "schema-expand-level" }) schemaExpandLevel = 99999;
73
+ @property({ type: String, attribute: "schema-description-expanded" }) schemaDescriptionExpanded =
74
+ "false";
75
+ @property({ type: String, attribute: "allow-schema-description-expand-toggle" })
76
+ allowSchemaDescriptionExpandToggle = "false";
77
+ @property({ type: String, attribute: "schema-hide-read-only" }) schemaHideReadOnly = "true";
78
+ @property({ type: String, attribute: "schema-hide-write-only" }) schemaHideWriteOnly = "true";
79
+
80
+ willUpdate(changedProperties) {
81
+ super.willUpdate?.(changedProperties);
82
+ if (this.config && changedProperties.has("config")) {
83
+ if (this.config.schemaExpandLevel !== undefined)
84
+ this.schemaExpandLevel = this.config.schemaExpandLevel;
85
+ if (this.config.schemaDescriptionExpanded !== undefined)
86
+ this.schemaDescriptionExpanded = this.config.schemaDescriptionExpanded;
87
+ if (this.config.allowSchemaDescriptionExpandToggle !== undefined)
88
+ this.allowSchemaDescriptionExpandToggle = this.config.allowSchemaDescriptionExpandToggle;
89
+ this.schemaHideReadOnly = hideFlagFromConfig(
90
+ this.config.schemaHideReadOnly,
91
+ this.schemaHideReadOnly,
92
+ );
93
+ this.schemaHideWriteOnly = hideFlagFromConfig(
94
+ this.config.schemaHideWriteOnly,
95
+ this.schemaHideWriteOnly,
96
+ );
97
+ }
98
+ if (!this.schemaExpandLevel || this.schemaExpandLevel < 1) {
99
+ this.schemaExpandLevel = 99999;
100
+ }
101
+ if (!this.schemaDescriptionExpanded || !"true false".includes(this.schemaDescriptionExpanded)) {
102
+ this.schemaDescriptionExpanded = "false";
103
+ }
104
+ if (!this.schemaHideReadOnly || !"true false".includes(this.schemaHideReadOnly)) {
105
+ this.schemaHideReadOnly = "true";
106
+ }
107
+ if (!this.schemaHideWriteOnly || !"true false".includes(this.schemaHideWriteOnly)) {
108
+ this.schemaHideWriteOnly = "true";
109
+ }
110
+ }
111
+
112
+ handleAllEvents(e) {
113
+ const toggleTrigger = e.target.closest(".open-bracket, .obj-toggle");
114
+ if (toggleTrigger) {
115
+ this.toggleObjectExpand(toggleTrigger);
116
+ } else if (e.target.classList.contains("schema-multiline-toggle")) {
117
+ this.schemaDescriptionExpanded = this.schemaDescriptionExpanded === "true" ? "false" : "true";
118
+ } else if (e.target.closest(".descr-expand-toggle, .descr-body")) {
119
+ // Links inside a description still navigate, and selecting text to copy it doesn't toggle the row
120
+ if (
121
+ this.schemaDescriptionExpanded === "true" ||
122
+ e.target.closest("a") ||
123
+ window.getSelection()?.isCollapsed === false
124
+ ) {
125
+ return;
126
+ }
127
+ const trEl = e.target.closest(".tr");
128
+ if (
129
+ trEl &&
130
+ (trEl.classList.contains("expanded-descr") ||
131
+ this.descrHasMore(e.target.closest(".descr-body")))
132
+ ) {
133
+ const isExpanded = trEl.classList.toggle("expanded-descr");
134
+ trEl
135
+ .querySelector(".descr-expand-toggle")
136
+ ?.setAttribute("aria-expanded", isExpanded ? "true" : "false");
137
+ }
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Whether a collapsed description has more to show, so a click expands it: CSS shows the arrow for those rows,
143
+ * and a line cut off for length counts too (browsers without scroll-state queries can't show the arrow for it).
144
+ * Read at click time only; nothing measures rows as they render or resize.
145
+ */
146
+ descrHasMore(bodyEl) {
147
+ if (!bodyEl) {
148
+ return false;
149
+ }
150
+ const toggleEl = bodyEl.querySelector(":scope > .descr-expand-toggle");
151
+ return (
152
+ (toggleEl && getComputedStyle(toggleEl).visibility === "visible") ||
153
+ bodyEl.scrollWidth > bodyEl.clientWidth
154
+ );
155
+ }
156
+
157
+ handleKeyDown(e) {
158
+ if (e.key === "Enter" || e.key === " ") {
159
+ const toggleTrigger = e.target.closest(
160
+ ".open-bracket, .obj-toggle, .descr-expand-toggle, .schema-multiline-toggle",
161
+ );
162
+ if (toggleTrigger) {
163
+ e.preventDefault();
164
+ toggleTrigger.click();
165
+ }
166
+ }
167
+ }
168
+
169
+ toggleObjectExpand(targetEl) {
170
+ const rowEl = targetEl.closest(".tr");
171
+ if (!rowEl) {
172
+ return;
173
+ }
174
+ const isExpanding = rowEl.classList.contains("collapsed");
175
+ if (isExpanding) {
176
+ rowEl.classList.replace("collapsed", "expanded");
177
+ } else {
178
+ rowEl.classList.replace("expanded", "collapsed");
179
+ }
180
+ const toggleEl = rowEl.querySelector(".open-bracket, .obj-toggle");
181
+ if (toggleEl) {
182
+ toggleEl.setAttribute("aria-expanded", isExpanding ? "true" : "false");
183
+ }
184
+ }
185
+
186
+ isFieldHidden(node) {
187
+ if (!node) {
188
+ return true;
189
+ }
190
+ if (this.schemaHideReadOnly === "true" && node.readOnly) {
191
+ return true;
192
+ }
193
+ if (this.schemaHideWriteOnly === "true" && node.writeOnly) {
194
+ return true;
195
+ }
196
+ return false;
197
+ }
198
+
199
+ // Ends with the space before the name, so rows without the icon have no whitespace node there
200
+ renderDeprecatedIcon(node) {
201
+ return node?.deprecated
202
+ ? html`<svg viewBox="0 0 10 10" width="10" height="10" style="stroke:var(--destructive); margin-right:-6px">
203
+ <path d="M2 2L8 8M2 8L8 2" />
204
+ </svg> `
205
+ : "";
206
+ }
207
+
208
+ getReadWriteBadge(node) {
209
+ return node?.readOnly ? html` 🆁` : node?.writeOnly ? html` 🆆` : "";
210
+ }
211
+
212
+ getReadWriteTip(node) {
213
+ return node?.readOnly ? "Read-Only" : node?.writeOnly ? "Write-Only" : "";
214
+ }
215
+
216
+ getDataTypeCss(type) {
217
+ return (type || "")
218
+ .replace(/┃.*/g, "")
219
+ .replace(/[^a-zA-Z0-9+]/g, "")
220
+ .substring(0, 4)
221
+ .toLowerCase();
222
+ }
223
+
224
+ hasDetailChips(node) {
225
+ return Boolean(
226
+ node &&
227
+ (node.constraints ||
228
+ node.defaultValue ||
229
+ node.allowedValues ||
230
+ node.pattern ||
231
+ node.contentMediaType ||
232
+ node.contentEncoding),
233
+ );
234
+ }
235
+
236
+ renderDetailChips(node) {
237
+ if (!node) {
238
+ return "";
239
+ }
240
+ return html`
241
+ ${node.constraints ? html`<div class="descr-chip"><span class="descr-label">Constraints:</span> <span class="descr-value">${node.constraints}</span></div>` : ""}
242
+ ${node.defaultValue ? html`<div class="descr-chip"><span class="descr-label">Default:</span> <span class="descr-value">${node.defaultValue}</span></div>` : ""}
243
+ ${node.allowedValues ? html`<div class="descr-chip"><span class="descr-label">${node.type === "const" ? "Value" : "Allowed"}:</span> <span class="descr-value">${node.allowedValues}</span></div>` : ""}
244
+ ${node.pattern ? html`<div class="descr-chip"><span class="descr-label">Pattern:</span> <span class="descr-value">${node.pattern}</span></div>` : ""}
245
+ ${node.contentMediaType ? html`<div class="descr-chip"><span class="descr-label">Media-Type:</span> <span class="descr-value">${node.contentMediaType}</span></div>` : ""}
246
+ ${node.contentEncoding ? html`<div class="descr-chip"><span class="descr-label">Encoding:</span> <span class="descr-value">${node.contentEncoding}</span></div>` : ""}
247
+ `;
248
+ }
249
+
250
+ renderDescriptionHtml(desc, title = "") {
251
+ if (!desc && !title) {
252
+ return "";
253
+ }
254
+ const text = title ? (desc ? `<b>${title}:</b> ${desc}` : `<b>${title}</b>`) : desc;
255
+ return html`${unsafeHTML(sanitizeHTML(marked(text)))}`;
256
+ }
257
+
258
+ /**
259
+ * Description cell shared by every schema row.
260
+ * Collapsed rows show only the first markdown block (or the constraint chips, when there is no description) on one line,
261
+ * and CSS marks a cut-off line with an ellipsis.
262
+ * A first block that cannot fit on one line (table, code block, HTML block, blockquote) is replaced there by a summary
263
+ * line (`.descr-summary`), which CSS shows only in collapsed rows. A title before any block other than a paragraph
264
+ * (list, heading, table, ...) gets a paragraph of its own, and the summary line is the title plus the block's first line.
265
+ * CSS shows the arrow when the row has hidden content (the `has-more` class: more markdown blocks, a line break,
266
+ * a summarized block, or chips under the text) or, where scroll-state container queries work, when the line is cut off.
267
+ * The arrow sits inside the description box so those queries can reach it.
268
+ *
269
+ * @param {string} desc - Markdown description
270
+ * @param {object} [chipsNode] - Node whose constraints, default, allowed values, etc. are shown as chips
271
+ * @param {string} [title] - Schema title, shown in bold before the description
272
+ */
273
+ renderDescrCell(desc, chipsNode = null, title = "") {
274
+ const text = typeof desc === "string" ? desc.trim() : "";
275
+ const hasChips = this.hasDetailChips(chipsNode);
276
+ if (!text && !title && !hasChips) {
277
+ return html`<div class="td key-descr"></div>`;
278
+ }
279
+ let body;
280
+ let hasMore;
281
+ if (isPlainText(text) && isPlainText(title)) {
282
+ // Most descriptions are plain sentences: shown as they are, without the markdown parser, the sanitizer and the HTML parse
283
+ body = title
284
+ ? html`<p><b>${title}${text ? ":" : ""}</b> ${text}</p>`
285
+ : text
286
+ ? html`<p>${text}</p>`
287
+ : "";
288
+ hasMore = hasChips && !!body;
289
+ } else {
290
+ const rendered = renderMarkdownDescription(text, title);
291
+ body = html`${rendered.summary ? html`<span class="descr-summary">${unsafeHTML(rendered.summary)}</span>` : ""}${rendered.html ? unsafeHTML(rendered.html) : ""}`;
292
+ hasMore = rendered.hasMore || (!!rendered.html && hasChips);
293
+ }
294
+ const isExpanded = this.schemaDescriptionExpanded === "true";
295
+ // The arrow, the text and the chips sit next to each other: whitespace between them would be a text node per row
296
+ return html`
297
+ <div class="td key-descr">
298
+ <div class="descr-body m-markdown-small ${hasMore ? "has-more" : ""}">
299
+ <span
300
+ class="descr-expand-toggle"
301
+ role="button"
302
+ tabindex="0"
303
+ aria-label="Toggle description"
304
+ aria-expanded="${isExpanded ? "true" : "false"}"
305
+ >➔</span
306
+ >${body}${hasChips ? html`<div class="item-details">${this.renderDetailChips(chipsNode)}</div>` : ""}
307
+ </div>
308
+ </div>
309
+ `;
310
+ }
311
+
312
+ renderToolbar(rootType) {
313
+ return html`
314
+ <div class="toolbar">
315
+ <div class="toolbar-item schema-root-type ${rootType} ">${rootType}</div>
316
+ ${
317
+ this.allowSchemaDescriptionExpandToggle === "true"
318
+ ? html`
319
+ <div style="flex:1"></div>
320
+ <div part="schema-toolbar-item schema-multiline-toggle" class="toolbar-item schema-multiline-toggle">
321
+ ${this.schemaDescriptionExpanded === "true" ? "Single line description" : "Multiline description"}
322
+ </div>
323
+ `
324
+ : ""
325
+ }
326
+ </div>
327
+ `;
328
+ }
329
+ }