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,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isomorphic HTML serializer for Lit TemplateResult in Node.js, Bun, and SSR/SSG runtimes.
|
|
3
|
+
*
|
|
4
|
+
* Flattens declarative Lit templates into pure, static HTML strings without requiring
|
|
5
|
+
* a browser window, headless browser, or full DOM emulator (JSDOM/HappyDOM).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Minimal polyfill for customElements registry in pure Node/Bun environments
|
|
9
|
+
if (typeof globalThis.customElements === "undefined") {
|
|
10
|
+
globalThis.customElements = {
|
|
11
|
+
define: () => {},
|
|
12
|
+
get: () => undefined,
|
|
13
|
+
whenDefined: () => Promise.resolve(),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Escapes characters for HTML text nodes and attribute values to prevent injection.
|
|
19
|
+
* @param {string} str
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
export function escapeHtml(str) {
|
|
23
|
+
if (typeof str !== "string") return String(str ?? "");
|
|
24
|
+
return str
|
|
25
|
+
.replace(/&/g, "&")
|
|
26
|
+
.replace(/</g, "<")
|
|
27
|
+
.replace(/>/g, ">")
|
|
28
|
+
.replace(/"/g, """)
|
|
29
|
+
.replace(/'/g, "'");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Escapes characters for HTML text nodes (quotes are left as is, since they are inert in text).
|
|
34
|
+
* @param {string} str
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
function escapeText(str) {
|
|
38
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Directives whose value is inserted as markup, matching Lit's behavior in the browser.
|
|
43
|
+
* Matched by the static `directiveName` (survives minification, unlike class names).
|
|
44
|
+
*/
|
|
45
|
+
const RAW_MARKUP_DIRECTIVES = new Set(["unsafeHTML", "unsafeSVG"]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Recursively serializes a Lit TemplateResult, directive, CSSResult, primitive, or array
|
|
49
|
+
* into a pure static HTML string.
|
|
50
|
+
*
|
|
51
|
+
* - Event listeners (`@click="..."`) are stripped.
|
|
52
|
+
* - Non-attribute property bindings (`.prop="..."`) are stripped.
|
|
53
|
+
* - Boolean attributes (`?disabled="..."`) are converted to standard HTML attributes if truthy, or omitted if falsy.
|
|
54
|
+
* - Strings from plain bindings are HTML-escaped, as Lit does in the browser (`&<>` in text,
|
|
55
|
+
* plus quotes in attribute values). Unquoted attribute bindings (`value=${x}`) are quoted.
|
|
56
|
+
* - Lit directives (`unsafeHTML`, `ifDefined`, `guard`) are evaluated transparently; only
|
|
57
|
+
* `unsafeHTML` / `unsafeSVG` values are inserted as raw markup. An attribute whose whole value is
|
|
58
|
+
* `nothing` (e.g. `ifDefined(undefined)`) is omitted.
|
|
59
|
+
* - CSSResult instances (`css\`...\``) are resolved via their `.cssText` property.
|
|
60
|
+
*
|
|
61
|
+
* @param {any} result - The value or TemplateResult to serialize.
|
|
62
|
+
* @param {Object} [options]
|
|
63
|
+
* @param {boolean} [options.stripComments=false] - Whether to strip HTML comments.
|
|
64
|
+
* @returns {string} Serialized HTML string.
|
|
65
|
+
*/
|
|
66
|
+
export function renderTemplateToString(result, options = {}) {
|
|
67
|
+
return serializeValue(result, options, false);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {any} result
|
|
72
|
+
* @param {Object} options
|
|
73
|
+
* @param {boolean} inAttribute - Whether the value is bound inside an attribute value.
|
|
74
|
+
* @returns {string}
|
|
75
|
+
*/
|
|
76
|
+
function serializeValue(result, options, inAttribute) {
|
|
77
|
+
if (result == null || result === false) {
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (typeof result === "string") {
|
|
82
|
+
return inAttribute ? escapeHtml(result) : escapeText(result);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (typeof result === "number" || typeof result === "bigint") {
|
|
86
|
+
return String(result);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (typeof result === "symbol") {
|
|
90
|
+
return "";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (Array.isArray(result)) {
|
|
94
|
+
return result.map((item) => serializeValue(item, options, inAttribute)).join("");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Handle Lit CSSResult
|
|
98
|
+
if (typeof result === "object" && result.cssText) {
|
|
99
|
+
return result.cssText;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Handle Lit directives (unsafeHTML, guard, live)
|
|
103
|
+
if (typeof result === "object" && result._$litDirective$) {
|
|
104
|
+
// unsafeHTML(str) / unsafeSVG(str): inserted as markup, never escaped
|
|
105
|
+
if (RAW_MARKUP_DIRECTIVES.has(result._$litDirective$.directiveName)) {
|
|
106
|
+
const markup = result.values?.[0];
|
|
107
|
+
return typeof markup === "string" ? markup : serializeValue(markup, options, inAttribute);
|
|
108
|
+
}
|
|
109
|
+
// guard([deps], () => fn)
|
|
110
|
+
if (result.values && typeof result.values[1] === "function") {
|
|
111
|
+
return serializeValue(result.values[1](), options, inAttribute);
|
|
112
|
+
}
|
|
113
|
+
// live(value) and other value-passing directives
|
|
114
|
+
if (result.values && result.values.length > 0) {
|
|
115
|
+
return serializeValue(result.values[0], options, inAttribute);
|
|
116
|
+
}
|
|
117
|
+
return "";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Handle Lit TemplateResult
|
|
121
|
+
if (typeof result === "object" && "strings" in result && "values" in result) {
|
|
122
|
+
let out = "";
|
|
123
|
+
let skipNextLeadingQuote = false;
|
|
124
|
+
// Whether the parser position is inside a start tag (between `<` and `>`), so a binding is an attribute value
|
|
125
|
+
let inTag = false;
|
|
126
|
+
|
|
127
|
+
for (let i = 0; i < result.strings.length; i++) {
|
|
128
|
+
let str = result.strings[i];
|
|
129
|
+
const lastOpen = str.lastIndexOf("<");
|
|
130
|
+
const lastClose = str.lastIndexOf(">");
|
|
131
|
+
if (lastOpen !== lastClose) {
|
|
132
|
+
inTag = lastOpen > lastClose;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Strip matching quote from previous expression if skipped
|
|
136
|
+
if (skipNextLeadingQuote) {
|
|
137
|
+
if (str.startsWith('"') || str.startsWith("'")) {
|
|
138
|
+
str = str.slice(1);
|
|
139
|
+
}
|
|
140
|
+
skipNextLeadingQuote = false;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (i < result.values.length) {
|
|
144
|
+
const val = result.values[i];
|
|
145
|
+
|
|
146
|
+
// 1. Event bindings: e.g. @click="..." or @click=...
|
|
147
|
+
const eventMatch = str.match(/@([\w.-]+)=(["']?)$/);
|
|
148
|
+
if (eventMatch) {
|
|
149
|
+
str = str.slice(0, eventMatch.index).trimEnd();
|
|
150
|
+
if (eventMatch[2]) {
|
|
151
|
+
skipNextLeadingQuote = true;
|
|
152
|
+
}
|
|
153
|
+
out += str;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 2. Property bindings: e.g. .config="..." or .config=...
|
|
158
|
+
const propMatch = str.match(/\.([\w.-]+)=(["']?)$/);
|
|
159
|
+
if (propMatch) {
|
|
160
|
+
str = str.slice(0, propMatch.index).trimEnd();
|
|
161
|
+
if (propMatch[2]) {
|
|
162
|
+
skipNextLeadingQuote = true;
|
|
163
|
+
}
|
|
164
|
+
out += str;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 3. Boolean attributes: e.g. ?disabled="..." or ?disabled=...
|
|
169
|
+
const boolMatch = str.match(/\?([\w.-]+)=(["']?)$/);
|
|
170
|
+
if (boolMatch) {
|
|
171
|
+
const attrName = boolMatch[1];
|
|
172
|
+
const hasQuote = Boolean(boolMatch[2]);
|
|
173
|
+
str = str.slice(0, boolMatch.index).trimEnd();
|
|
174
|
+
if (hasQuote) {
|
|
175
|
+
skipNextLeadingQuote = true;
|
|
176
|
+
}
|
|
177
|
+
const isTruthy = Boolean(val && val !== "false");
|
|
178
|
+
out += str + (isTruthy ? ` ${attrName}` : "");
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 4. Regular attribute or text node
|
|
183
|
+
const attrMatch = inTag ? str.match(/\s[^\s"'>/=]+=(["']?)$/) : null;
|
|
184
|
+
if (
|
|
185
|
+
attrMatch &&
|
|
186
|
+
typeof val === "symbol" &&
|
|
187
|
+
(!attrMatch[1] || result.strings[i + 1]?.startsWith(attrMatch[1]))
|
|
188
|
+
) {
|
|
189
|
+
// `nothing` (e.g. ifDefined(undefined)) as the whole attribute value removes the attribute, as Lit does
|
|
190
|
+
out += str.slice(0, attrMatch.index);
|
|
191
|
+
skipNextLeadingQuote = Boolean(attrMatch[1]);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (attrMatch && !attrMatch[1]) {
|
|
195
|
+
// Unquoted attribute binding: quote it so an escaped value cannot break out into new attributes
|
|
196
|
+
out += `${str}"${serializeValue(val, options, true)}"`;
|
|
197
|
+
} else {
|
|
198
|
+
out += str;
|
|
199
|
+
out += serializeValue(val, options, inTag);
|
|
200
|
+
}
|
|
201
|
+
} else {
|
|
202
|
+
out += str;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (options.stripComments) {
|
|
207
|
+
out = out.replace(/<!--[\s\S]*?-->/g, "");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return "";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export default renderTemplateToString;
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Authentication: the security-scheme list in the Authentication section and the
|
|
5
|
+
* security chips on each operation. Loaded by <rapi-doc> and <rapi-doc-mini>.
|
|
6
|
+
*/
|
|
7
|
+
export default css`
|
|
8
|
+
/* Authentication: one list item per security scheme; OAuth flows nest inside their scheme. */
|
|
9
|
+
.auth-status {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-wrap: wrap;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: space-between;
|
|
14
|
+
gap: 0.5rem;
|
|
15
|
+
margin-bottom: 0.5rem;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.auth-list {
|
|
19
|
+
container-type: inline-size;
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: 0;
|
|
22
|
+
list-style: none;
|
|
23
|
+
border: 1px solid var(--border);
|
|
24
|
+
border-radius: min(var(--radius), 0.5rem);
|
|
25
|
+
/* Card surface, same as .param-list */
|
|
26
|
+
background: color-mix(in srgb, var(--card) 80%, transparent);
|
|
27
|
+
font-size: var(--font-size-small);
|
|
28
|
+
line-height: 1.5;
|
|
29
|
+
direction: ltr;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.auth-scheme {
|
|
33
|
+
padding: calc(var(--auth-scheme-padding) * 1.5);
|
|
34
|
+
margin: 0;
|
|
35
|
+
overflow-wrap: break-word;
|
|
36
|
+
|
|
37
|
+
& + .auth-scheme {
|
|
38
|
+
border-top: 1px solid var(--border);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Each block of a scheme (header, description, hint, controls, flows) is spaced by the same gap */
|
|
43
|
+
.auth-scheme-body,
|
|
44
|
+
.oauth-flow {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
align-items: flex-start;
|
|
48
|
+
gap: 0.75em;
|
|
49
|
+
|
|
50
|
+
& > * {
|
|
51
|
+
margin: 0;
|
|
52
|
+
max-width: 100%;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.auth-scheme-header {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-wrap: wrap;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: 0.5em;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.auth-scheme-title {
|
|
64
|
+
font-size: var(--font-size-regular);
|
|
65
|
+
font-weight: 600;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Prose (description, "Send X in header") keeps a readable line length */
|
|
69
|
+
.auth-scheme-body > .m-markdown,
|
|
70
|
+
.auth-hint,
|
|
71
|
+
.auth-host-note {
|
|
72
|
+
max-width: 70ch;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* "Use a different token" under a host note: a text link, not a full-size button */
|
|
76
|
+
.auth-host-toggle {
|
|
77
|
+
font-size: var(--font-size-small);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* Inputs and their button on a grid of equal columns (12em-16em), so a field that wraps to the next
|
|
82
|
+
* line keeps the width of the one above it; the button sits at the start of its cell.
|
|
83
|
+
*/
|
|
84
|
+
.auth-controls {
|
|
85
|
+
display: grid;
|
|
86
|
+
grid-template-columns: repeat(auto-fill, minmax(12em, 16em));
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: 0.5em;
|
|
89
|
+
width: 100%;
|
|
90
|
+
|
|
91
|
+
& > :is(input, select) {
|
|
92
|
+
width: 100%;
|
|
93
|
+
min-width: 0;
|
|
94
|
+
box-sizing: border-box;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
& > .btn {
|
|
98
|
+
justify-self: start;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* OAuth flows: one after another, each opened by its heading and parted from the previous one by a dashed rule */
|
|
103
|
+
.oauth-flow {
|
|
104
|
+
padding-block: 1.25em;
|
|
105
|
+
|
|
106
|
+
& + .oauth-flow {
|
|
107
|
+
border-top: 1px dashed var(--border);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&:last-child {
|
|
111
|
+
padding-bottom: 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
& > .tiny-title {
|
|
115
|
+
margin: 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.oauth-urls {
|
|
120
|
+
display: grid;
|
|
121
|
+
grid-template-columns: max-content minmax(0, 1fr);
|
|
122
|
+
gap: 0.25em 1.5em;
|
|
123
|
+
|
|
124
|
+
& > dt {
|
|
125
|
+
color: var(--muted-foreground);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
& > dd {
|
|
129
|
+
margin: 0;
|
|
130
|
+
overflow-wrap: anywhere;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.oauth-scopes-label {
|
|
135
|
+
color: var(--muted-foreground);
|
|
136
|
+
margin-bottom: -0.25em;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.oauth-scopes {
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-direction: column;
|
|
142
|
+
gap: 0.5em;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Scope value in the foreground color, its description muted, with a dash between */
|
|
146
|
+
.oauth-scope-name {
|
|
147
|
+
color: var(--foreground);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.oauth-scope-descr {
|
|
151
|
+
color: var(--muted-foreground);
|
|
152
|
+
|
|
153
|
+
&::before {
|
|
154
|
+
content: '– ';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Toggle + its text; the text wraps beside the toggle, not under it. The toggle is 1.5em tall,
|
|
159
|
+
the same as one line of text here, so it lines up with the first line. */
|
|
160
|
+
.auth-toggle {
|
|
161
|
+
display: inline-flex;
|
|
162
|
+
align-items: flex-start;
|
|
163
|
+
gap: 0.625em;
|
|
164
|
+
cursor: pointer;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.oauth-resp-display:empty {
|
|
168
|
+
display: none;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* Narrow containers: fields take the full row; URL labels stack above their values */
|
|
172
|
+
@container (max-width: 30rem) {
|
|
173
|
+
.auth-controls {
|
|
174
|
+
grid-template-columns: minmax(0, 1fr);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.oauth-urls {
|
|
178
|
+
grid-template-columns: minmax(0, 1fr);
|
|
179
|
+
|
|
180
|
+
& > dd + dt {
|
|
181
|
+
margin-top: 0.375em;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* Operation security: a lock, then a row of chips right under the method and path, one per alternative,
|
|
188
|
+
* with "OR" between them. The lock marks the row as authorization (and links to the Authentication
|
|
189
|
+
* section when that is shown); a chip opens its details popover on hover or focus.
|
|
190
|
+
*/
|
|
191
|
+
.operation-security {
|
|
192
|
+
display: flex;
|
|
193
|
+
align-items: flex-start;
|
|
194
|
+
gap: 0.375em;
|
|
195
|
+
margin: 0 0 12px;
|
|
196
|
+
min-width: 0;
|
|
197
|
+
max-width: 100%;
|
|
198
|
+
font-size: var(--font-size-small);
|
|
199
|
+
line-height: 1.25;
|
|
200
|
+
}
|
|
201
|
+
.security-chips {
|
|
202
|
+
align-items: center;
|
|
203
|
+
row-gap: 6px;
|
|
204
|
+
|
|
205
|
+
/* Keeps "OR" centered on the chip beside it */
|
|
206
|
+
& > li {
|
|
207
|
+
display: inline-flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
.value-list-items.security-chips > li:not(:last-child)::after {
|
|
212
|
+
content: 'OR';
|
|
213
|
+
margin-inline: 0.625em;
|
|
214
|
+
font-size: var(--font-size-xs);
|
|
215
|
+
letter-spacing: 0.04em;
|
|
216
|
+
}
|
|
217
|
+
.security-chip {
|
|
218
|
+
display: inline-flex;
|
|
219
|
+
align-items: center;
|
|
220
|
+
gap: 0.375em;
|
|
221
|
+
min-width: 0;
|
|
222
|
+
max-width: 100%;
|
|
223
|
+
padding: 0.25em 0.625em;
|
|
224
|
+
color: var(--foreground);
|
|
225
|
+
background: color-mix(in srgb, var(--card) 80%, transparent);
|
|
226
|
+
border: 1px solid var(--input);
|
|
227
|
+
/* Same radius as buttons, inputs and the popover it opens */
|
|
228
|
+
border-radius: var(--radius);
|
|
229
|
+
transition:
|
|
230
|
+
color 0.15s ease,
|
|
231
|
+
border-color 0.15s ease;
|
|
232
|
+
|
|
233
|
+
&.has-details {
|
|
234
|
+
cursor: pointer;
|
|
235
|
+
}
|
|
236
|
+
&.has-details:is(:hover, :focus-within) {
|
|
237
|
+
color: var(--primary);
|
|
238
|
+
border-color: var(--primary);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/* Same size as a chip (and .btn-sm), so it lines up with the first row of chips */
|
|
242
|
+
.security-lock-btn {
|
|
243
|
+
display: inline-flex;
|
|
244
|
+
flex: none;
|
|
245
|
+
align-items: center;
|
|
246
|
+
justify-content: center;
|
|
247
|
+
width: calc(1.75em + 2px);
|
|
248
|
+
height: calc(1.75em + 2px);
|
|
249
|
+
color: var(--muted-foreground);
|
|
250
|
+
border-radius: var(--radius);
|
|
251
|
+
}
|
|
252
|
+
a.security-lock-btn {
|
|
253
|
+
transition:
|
|
254
|
+
color 0.15s ease,
|
|
255
|
+
background-color 0.15s ease;
|
|
256
|
+
|
|
257
|
+
&:hover {
|
|
258
|
+
color: var(--foreground);
|
|
259
|
+
background: var(--muted);
|
|
260
|
+
}
|
|
261
|
+
&:focus-visible {
|
|
262
|
+
outline: none;
|
|
263
|
+
box-shadow: var(--focus-shadow);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
.security-lock {
|
|
267
|
+
width: 1.25em;
|
|
268
|
+
height: 1.25em;
|
|
269
|
+
stroke: currentColor;
|
|
270
|
+
stroke-linecap: round;
|
|
271
|
+
stroke-linejoin: round;
|
|
272
|
+
}
|
|
273
|
+
.security-chip-label {
|
|
274
|
+
display: block;
|
|
275
|
+
max-width: 240px;
|
|
276
|
+
padding: 0;
|
|
277
|
+
overflow: hidden;
|
|
278
|
+
white-space: nowrap;
|
|
279
|
+
text-overflow: ellipsis;
|
|
280
|
+
color: inherit;
|
|
281
|
+
text-decoration: none;
|
|
282
|
+
font: inherit;
|
|
283
|
+
background: none;
|
|
284
|
+
border: none;
|
|
285
|
+
border-radius: 0;
|
|
286
|
+
cursor: inherit;
|
|
287
|
+
|
|
288
|
+
&:focus-visible {
|
|
289
|
+
outline: 2px solid var(--ring);
|
|
290
|
+
outline-offset: 2px;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* Scheme details for a chip: a top-layer popover anchored below it (above when there is no room) */
|
|
295
|
+
/* Left edge on the chip's left edge, 6px below it; a page-colored surface with a thin border and a soft, tight shadow */
|
|
296
|
+
.security-popover {
|
|
297
|
+
inset: auto;
|
|
298
|
+
margin: 6px 0 6px 0;
|
|
299
|
+
position-area: bottom span-right;
|
|
300
|
+
position-try-fallbacks: flip-block;
|
|
301
|
+
width: max-content;
|
|
302
|
+
max-width: min(400px, calc(100vw - 16px));
|
|
303
|
+
padding: 0.75em 1em;
|
|
304
|
+
color: var(--foreground);
|
|
305
|
+
background: var(--background);
|
|
306
|
+
border: 1px solid var(--border);
|
|
307
|
+
border-radius: var(--radius);
|
|
308
|
+
box-shadow:
|
|
309
|
+
0 1px 2px rgba(0, 0, 0, 0.06),
|
|
310
|
+
0 4px 12px rgba(0, 0, 0, 0.08);
|
|
311
|
+
font-family: var(--font-sans);
|
|
312
|
+
font-size: var(--font-size-description);
|
|
313
|
+
line-height: 1.5;
|
|
314
|
+
text-align: start;
|
|
315
|
+
overflow-wrap: anywhere;
|
|
316
|
+
cursor: auto;
|
|
317
|
+
}
|
|
318
|
+
`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
|
|
3
|
+
export default css`
|
|
4
|
+
.border-top {
|
|
5
|
+
border-top: 1px solid var(--border);
|
|
6
|
+
}
|
|
7
|
+
.border {
|
|
8
|
+
border: 1px solid var(--border);
|
|
9
|
+
border-radius: min(var(--radius), 0.5rem);
|
|
10
|
+
}
|
|
11
|
+
.light-border {
|
|
12
|
+
border: 1px solid var(--border);
|
|
13
|
+
border-radius: min(var(--radius), 0.5rem);
|
|
14
|
+
}
|
|
15
|
+
.pad-8-16 {
|
|
16
|
+
padding: 8px 16px;
|
|
17
|
+
}
|
|
18
|
+
.pad-top-8 {
|
|
19
|
+
padding-top: 8px;
|
|
20
|
+
}
|
|
21
|
+
.mar-top-8 {
|
|
22
|
+
margin-top: 8px;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import ThemeTokens, { DEFAULT_THEME } from "./theme-tokens.js";
|
|
2
|
+
import FontStyles from "./font-styles.js";
|
|
3
|
+
import InputStyles from "./input-styles.js";
|
|
4
|
+
import FlexStyles from "./flex-styles.js";
|
|
5
|
+
import AuthStyles from "./auth-styles.js";
|
|
6
|
+
import ParamListStyles from "./param-list-styles.js";
|
|
7
|
+
import EndpointStyles from "./endpoint-styles.js";
|
|
8
|
+
import MicrolighterStyles from "./microlighter-styles.js";
|
|
9
|
+
import TabStyles from "./tab-styles.js";
|
|
10
|
+
import NavStyles from "./nav-styles.js";
|
|
11
|
+
import InfoStyles from "./info-styles.js";
|
|
12
|
+
import DialogBoxStyles from "./dialog-box-styles.js";
|
|
13
|
+
import LayoutStyles from "./layout-styles.js";
|
|
14
|
+
import BorderStyles from "./border-styles.js";
|
|
15
|
+
import SchemaStyles from "./schema-styles.js";
|
|
16
|
+
import CustomStyles from "./custom-styles.js";
|
|
17
|
+
|
|
18
|
+
export const allStyles = [
|
|
19
|
+
ThemeTokens,
|
|
20
|
+
FontStyles,
|
|
21
|
+
InputStyles,
|
|
22
|
+
FlexStyles,
|
|
23
|
+
AuthStyles,
|
|
24
|
+
ParamListStyles,
|
|
25
|
+
BorderStyles,
|
|
26
|
+
EndpointStyles,
|
|
27
|
+
MicrolighterStyles,
|
|
28
|
+
TabStyles,
|
|
29
|
+
NavStyles,
|
|
30
|
+
InfoStyles,
|
|
31
|
+
DialogBoxStyles,
|
|
32
|
+
LayoutStyles,
|
|
33
|
+
SchemaStyles,
|
|
34
|
+
CustomStyles,
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Returns aggregated CSS text for Declarative Shadow DOM or Light DOM SSR/SSG pre-rendering.
|
|
39
|
+
*
|
|
40
|
+
* @param {Object} [options]
|
|
41
|
+
* @param {string} [options.theme='ember'] - Theme preset name or valid hex color code
|
|
42
|
+
* @param {'dark'|'light'|'system'} [options.colorScheme='dark'] - Color scheme
|
|
43
|
+
* @param {string} [options.scope=''] - Optional outer selector (for Light DOM / non-shadow pre-rendering)
|
|
44
|
+
* @returns {string} Fully concatenated CSS string
|
|
45
|
+
*/
|
|
46
|
+
export function getBundledCss(options = {}) {
|
|
47
|
+
const { scope = "" } = options;
|
|
48
|
+
|
|
49
|
+
let combinedCss = allStyles.map((s) => (s && s.cssText ? s.cssText : String(s || ""))).join("\n");
|
|
50
|
+
|
|
51
|
+
// If rendering in Light DOM without Shadow DOM, adapt :host selectors to the container
|
|
52
|
+
if (scope && scope !== ":host") {
|
|
53
|
+
combinedCss = combinedCss
|
|
54
|
+
.replace(/:host\(([^)]+)\)/g, `${scope}$1`)
|
|
55
|
+
.replace(/:host\b/g, scope)
|
|
56
|
+
.replace(/::slotted\(([^)]+)\)/g, `$1`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return combinedCss;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Returns RapiDoc's navigation CSS text for shared usage in @rapidoc/portal.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} [scope=''] - Optional outer selector
|
|
66
|
+
* @returns {string} Navigation CSS string
|
|
67
|
+
*/
|
|
68
|
+
export function getNavCss(scope = "") {
|
|
69
|
+
let navCss = NavStyles && NavStyles.cssText ? NavStyles.cssText : String(NavStyles || "");
|
|
70
|
+
if (scope && scope !== ":host") {
|
|
71
|
+
navCss = navCss
|
|
72
|
+
.replace(
|
|
73
|
+
/:host\(\[color-scheme='([^']+)'\]\)/g,
|
|
74
|
+
`[data-theme='$1'] ${scope}, ${scope}[color-scheme='$1']`,
|
|
75
|
+
)
|
|
76
|
+
.replace(/:host\(([^)]+)\)/g, `${scope}$1`)
|
|
77
|
+
.replace(/:host\b/g, scope)
|
|
78
|
+
.replace(/::slotted\(([^)]+)\)/g, `$1`)
|
|
79
|
+
.replace(/^\s*\.nav-bar\s*\{/gm, "&.nav-bar, & {");
|
|
80
|
+
navCss = `${scope} {\n --sidebar-item-padding: 0.3125rem 1rem 0.3125rem 0.625rem;\n${navCss}\n}\n[data-theme='light'] ${scope} .nav-method.as-colored-block {\n color: var(--method-badge-fg);\n}\n`;
|
|
81
|
+
}
|
|
82
|
+
return navCss;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns RapiDoc's design system & theme tokens CSS text for shared usage in @rapidoc/portal.
|
|
87
|
+
* Converts Web Component :host rules into Light DOM portal selectors (:root, [data-theme='dark'], [data-theme='light']).
|
|
88
|
+
*
|
|
89
|
+
* @param {string} [theme='ember'] - Theme preset name (see THEME_PRESETS) or hex color
|
|
90
|
+
* @param {string} [scope=':root'] - Scope selector
|
|
91
|
+
* @returns {string} Theme tokens CSS string
|
|
92
|
+
*/
|
|
93
|
+
export function getThemeTokensCss(theme = DEFAULT_THEME, scope = ":root") {
|
|
94
|
+
let tokensCss =
|
|
95
|
+
ThemeTokens && ThemeTokens.cssText ? ThemeTokens.cssText : String(ThemeTokens || "");
|
|
96
|
+
const activeTheme =
|
|
97
|
+
typeof theme === "string"
|
|
98
|
+
? theme.trim().toLowerCase()
|
|
99
|
+
: typeof theme === "object" && theme?.theme
|
|
100
|
+
? String(theme.theme).trim().toLowerCase()
|
|
101
|
+
: DEFAULT_THEME;
|
|
102
|
+
|
|
103
|
+
tokensCss = tokensCss
|
|
104
|
+
.replace(/:host\(\[theme='([^']+)'\]\[color-scheme='light'\]\)/g, (match, t) =>
|
|
105
|
+
t === activeTheme ? "[data-theme='light']" : `[data-theme='light'][data-theme-preset='${t}']`,
|
|
106
|
+
)
|
|
107
|
+
.replace(/:host\(\[theme='([^']+)'\]\[color-scheme='system'\]\)/g, (match, t) =>
|
|
108
|
+
t === activeTheme
|
|
109
|
+
? "[data-theme='system']"
|
|
110
|
+
: `[data-theme='system'][data-theme-preset='${t}']`,
|
|
111
|
+
)
|
|
112
|
+
.replace(/:host\(\[theme='([^']+)'\]\)/g, (match, t) =>
|
|
113
|
+
t === activeTheme
|
|
114
|
+
? `${scope}, [data-theme='dark']`
|
|
115
|
+
: `[data-theme='dark'][data-theme-preset='${t}']`,
|
|
116
|
+
)
|
|
117
|
+
.replace(/:host\(:not\(\[theme\]\)\[color-scheme='light'\]\)/g, "[data-theme='light']")
|
|
118
|
+
.replace(/:host\(:not\(\[theme\]\)\[color-scheme='system'\]\)/g, "[data-theme='system']")
|
|
119
|
+
.replace(/:host\(:not\(\[theme\]\)\)/g, `${scope}, [data-theme='dark']`)
|
|
120
|
+
.replace(/:host\(\[color-scheme='light'\]\)/g, "[data-theme='light']")
|
|
121
|
+
.replace(/:host\(\[color-scheme='dark'\]\)/g, "[data-theme='dark']")
|
|
122
|
+
.replace(/:host\(\[color-scheme='system'\]\)/g, "[data-theme='system']")
|
|
123
|
+
.replace(/:host\(:not\(\[color-scheme\]\)\)/g, `${scope}, [data-theme='dark']`)
|
|
124
|
+
.replace(/:host\b/g, scope);
|
|
125
|
+
|
|
126
|
+
return tokensCss;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export default getBundledCss;
|