Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# `html/render-shell` — Altair HTML shell builder
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`html/render-shell` produces the single HTML document the Altair UI
|
||||
plugin serves at `<uiEndpoint>`. The shell mounts a `<div id="altair-root">`,
|
||||
embeds the resolved JS/CSS asset URLs (hash-busted, so CDN cache
|
||||
behaviour is correct), and serialises the parsed `AltairUiOptions` as a
|
||||
`<script type="application/json">` data block — never as executable
|
||||
inline JavaScript — so the strict CSP attached by `headers/csp` can
|
||||
forbid `script-src 'unsafe-inline'` outright.
|
||||
|
||||
## Features
|
||||
|
||||
- One self-contained HTML document — no external host references.
|
||||
- Configurable endpoints surfaced both as `<meta>` tags AND as `data-*`
|
||||
attributes on the root container, so consumers integrating Altair
|
||||
via custom JS can read either layer.
|
||||
- JSON config block escaped against `</script>` injection per the HTML5
|
||||
spec recommendation.
|
||||
- User-supplied endpoint values HTML-escaped before embedding.
|
||||
- Theme attribute (`data-altair-theme`) on `<html>` for CSS hooks.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { renderAltairShell } from "@suaveplan/api-graphql-ui-altair/html";
|
||||
import { buildDefaultAssetRegistry } from "@suaveplan/api-graphql-ui-altair/assets";
|
||||
import { parseAltairUiOptions } from "@suaveplan/api-graphql-ui-altair/options";
|
||||
|
||||
const html = renderAltairShell({
|
||||
options: parseAltairUiOptions(),
|
||||
assetRegistry: buildDefaultAssetRegistry(),
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { renderAltairShell } from "@suaveplan/api-graphql-ui-altair/html";
|
||||
import {
|
||||
buildDefaultAssetRegistry,
|
||||
defineAsset,
|
||||
} from "@suaveplan/api-graphql-ui-altair/assets";
|
||||
import { parseAltairUiOptions } from "@suaveplan/api-graphql-ui-altair/options";
|
||||
|
||||
const registry = new Map(buildDefaultAssetRegistry());
|
||||
registry.set(
|
||||
"logo.svg",
|
||||
defineAsset("logo.svg", "image/svg+xml", "<svg/>")
|
||||
);
|
||||
|
||||
const html = renderAltairShell({
|
||||
options: parseAltairUiOptions({
|
||||
theme: "dark",
|
||||
initialEnvironments: {
|
||||
production: { url: "https://api.example.com/graphql" },
|
||||
},
|
||||
}),
|
||||
assetRegistry: registry,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `RenderAltairShellInput` — `{ options: AltairUiOptions; assetRegistry: ReadonlyMap<string, BundledAsset> }`.
|
||||
- `renderAltairShell(input): string` — returns the full HTML document
|
||||
including the `<!DOCTYPE html>` declaration.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The `</script>` escape inside the JSON config block uses the HTML5
|
||||
spec's recommended sequence `<\/script` so the JSON itself remains
|
||||
parseable while the closing-tag-injection vector is closed. All
|
||||
user-supplied strings flowing into HTML attributes pass through a
|
||||
four-character HTML escape — the structural goal is "no inline script
|
||||
ever executes", which the strict CSP then enforces at the browser.
|
||||
Reference in New Issue
Block a user