Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
# `html/render-shell`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Renders the GraphiQL HTML shell. The output embeds the configured GraphQL
endpoint, subscription endpoint, theme, and editor passthroughs into a
`<script id="graphiql-config" type="application/json">` block — NOT inline
JavaScript — which the bundled `graphiql.js` parses at boot. This split
keeps `script-src 'self'` viable.
The shell is intentionally minimalist. The bundled bootstrap drives the
explorer end-to-end (text area for the query, JSON pre for the response).
Operators who want the full React-based GraphiQL distribution can swap
out the asset payload on a fork.
## Features
- Single-call render — `renderShell(options)` returns the full document.
- Defensive escaping — every caller-supplied string (default query,
endpoints, theme, editor options blob) is HTML-escaped.
- No external host references — every `src` / `href` points inside
`<uiEndpoint>/assets/`.
- Asset paths embed FNV-1a hashes for cache-busting.
## Usage: Basic
```ts
import {
parseGraphiqlUiOptions,
renderShell,
} from "@suaveplan/api-graphql-ui-graphiql";
const html = renderShell(parseGraphiqlUiOptions({}));
// html starts with <!DOCTYPE html> and references /graphql/ui/assets/...
```
## Usage: Advanced
```ts
import {
parseGraphiqlUiOptions,
renderShell,
} from "@suaveplan/api-graphql-ui-graphiql";
const html = renderShell(
parseGraphiqlUiOptions({
uiEndpoint: "/explorer",
graphqlEndpoint: "/api/v2/gql",
subscriptionEndpoint: "/api/v2/gql/ws",
theme: "dark",
defaultQuery: "{ viewer { id name } }",
editorOptions: { lineWrapping: true, tabSize: 2 },
})
);
```
## API Reference
- `renderShell(options: GraphiqlUiOptions): string` — produces the
fully-substituted HTML document.
- `escapeHtml(input: string): string` — replaces `&`, `<`, `>`, `"`,
and `'` with HTML entities.
## Implementation Notes
The config block uses `application/json` so the bootstrap can call
`JSON.parse(node.textContent)` without sniffing or eval. Escaping the
JSON via `escapeHtml` is technically over-protective (JSON inside a
`<script type="application/json">` block doesn't need entity encoding
of `<`/`>`/`&` for syntax correctness, but it does need it for
defense-in-depth when the JSON contains a `</script>` substring) — we
err on the safe side and run every embedded string through
`escapeHtml`.