first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
# Scalar HTML shell renderer
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The render-shell module emits the HTML body returned by the Scalar UI
handler. It embeds the configured OpenAPI document URL into a
`<script id="scalar-config" type="application/json">` block (inert under
strict CSP — JSON is not a script-src vector), references the resolved
Scalar runtime URL (CDN or bundled), and renders a small status / path
listing placeholder so even the air-gapped bundled bootstrap has
something to populate. When the operator runs nonce-based CSP, the
`renderShell` API accepts a `nonce` value the renderer threads onto the
inline `<script>` tags.
## Features
- `escapeHtml(input)` — replaces `& < > " '` with their entity
equivalents. Used on every caller-supplied string embedded in the
shell.
- `renderShell({ options, openapiUrl, runtimeUrl, nonce? })` — emits the
full HTML body. The body references `openapiUrl` exactly once in the
Scalar configuration block per the requirement spec.
- Bundled-mode shells include a `<link rel="stylesheet">` to the local
CSS asset; cdn-mode shells omit the link because the upstream Scalar
bundle ships its own styles.
## Usage: Basic
```ts
import { renderShell } from "@suaveplan/api-openapi-ui-scalar/html";
import { parseScalarUiOptions } from "@suaveplan/api-openapi-ui-scalar/options";
const options = parseScalarUiOptions({ openapiUrl: "/openapi.json" });
const html = renderShell({
options,
openapiUrl: "/openapi.json",
runtimeUrl: "https://cdn.jsdelivr.net/npm/@scalar/api-reference",
});
```
## Usage: Advanced
```ts
import { renderShell } from "@suaveplan/api-openapi-ui-scalar/html";
import { parseScalarUiOptions } from "@suaveplan/api-openapi-ui-scalar/options";
const options = parseScalarUiOptions({
openapiUrl: "/openapi.json?plugin=billing",
theme: "deepSpace",
assetMode: "bundled",
});
// Per-request nonce for hosts running nonce-based CSP.
const html = renderShell({
options,
openapiUrl: options.openapiUrl,
runtimeUrl: "/docs/ui/scalar/assets/scalar.<hash>.js",
nonce: "n-9b2f7c2a",
});
// The body references the configured OpenAPI URL exactly once.
console.assert(html.split(options.openapiUrl).length - 1 === 1);
```
## API Reference
- `RenderShellInput` — `{ options, openapiUrl, runtimeUrl, nonce? }`.
- `renderShell(input)` — returns the full HTML body string.
- `escapeHtml(input)` — entity-escapes the five hazardous characters.
## Implementation Notes
The configuration block JSON is post-processed to replace every `<` with
its unicode escape so string values like `"foo</script>"` cannot
terminate the script tag. This is the same defence applied by the
sibling `api-graphql-ui-graphiql` package; the technique is documented
by OWASP and is the strictest path that keeps the policy free of
`'unsafe-inline'`. The OpenAPI URL is embedded inside the JSON block
exactly once — verified by the handler conformance test.